題目描述
有n行2列的格子陣,每個格子最多能填0~9 9個數,在初始狀態下有的格子已經填了數字不能再改變,在滿足每3行共6個格子的和始終相同的情況下,有多少種解法,答案對1e9+7取模
思路
還可提前特判一下,若這六個和的值大於54,那麼一定無解。
可以注意到,第1,4,7…行兩個格子之和大小一定相同,第2,5,8行兩個子大小一定相同,第3,6,9…行兩格子大小一定相同。所以我先計算出第一行格子的最小值和最大值,第二行格子所要求的最小值和最大值,第三行格子所要求的最小值和最大值,然後預處理一下所滿足的要求組,最後對每行進行方法計算。
如果一行數字爲8且兩個格子都爲空,那麼就有9種方法。
如果一個格子爲空或者都不爲空,都當作只有一種方法。
代碼
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
int a[N][2];
bool st[N][2]; // 判斷某行某列這個數值是否可以更改
LL res = 0;
int down[N], up[N]; // 記錄第i行的最大值和最小值
int maxnum[3], minnum[3]; // 因爲都成等差數列,其實就是0,1,2三行的大小比較
struct node {
int u, v, w;
};
vector<node> cacl;
void solve()
{
int n, k, m;
scanf("%d%d%d", &n, &k, &m);
if(k > 54 || n * 2 == m) {
puts("0");
return;
}
for(int i = 1; i <= m; i++) {
int x, y, num;
scanf("%d%d%d", &x, &y, &num);
a[x][y] = num;
st[x][y] = 1;
}
// 計算最大最小值
memset(maxnum, 0x3f, sizeof maxnum);
for(int i = 0; i < n; i++) {
down[i] = a[i][0] + a[i][1];
if(!st[i][0] && !st[i][1]) up[i] = min(18, k);
else if(st[i][0] && !st[i][1]) up[i] = 18 - 9 + a[i][0] ;
else if(!st[i][0] && st[i][1]) up[i] = 18 - 9 + a[i][1];
else up[i] = down[i];
maxnum[i % 3] = min(maxnum[i % 3], up[i]);
minnum[i % 3] = max(minnum[i % 3], down[i]);
}
// 預處理所有滿足的組
for(int u = minnum[0]; u <= maxnum[0]; u++) {
for(int v = minnum[1]; v <= maxnum[1]; v++) {
for(int w = minnum[2]; w <= maxnum[2]; w++) {
if(u + w + v == k) cacl.push_back({u, v, w});
}
}
}
// 方法數計算
LL res = 0;
for(int i = 0; i < cacl.size(); i++) {
int u = cacl[i].u, v = cacl[i].v, w = cacl[i].w;
LL num = 1;
for(int j = 0; j < n; j += 3) {
if(!st[j][0] && !st[j][1]) {
if(u < 10) num = num * (u + 1) % mod;
else num = num * (18 - u + 1) % mod;
}
}
for(int j = 1; j < n; j += 3) {
if(!st[j][0] && !st[j][1]) {
if(v < 10) num = num * (v + 1) % mod;
else num = num * (18 - v + 1) % mod;
}
}
for(int j = 2; j < n; j += 3) {
if(w == 0) break;
if(!st[j][0] && !st[j][1]) {
if(w < 10) num = num * (w + 1) % mod;
else num = num * (18 - w + 1) % mod;
}
}
res = (res + num) % mod;
}
printf("%lld\n", res);
}
int main()
{
//freopen("in.txt", "r", stdin);
solve();
return 0;
}