不努力永远都只能是菜鸡,菜鸡..
这题咋一眼看会觉得很难,但是呢.首先的矩阵大小是hw的,但是他只要求nm的任意加起来为奇数.当然题目似乎没讲只能填1~9的数..
你会发现假如第一个nm的矩阵确认,那么符合条件的填法也是确认了..
因为为了维护奇数,我平移一个数,移进来的数和移出去的数奇偶性一定是一样的,那么问题就变成了,填第一个n*m的矩阵满足各行各列都是奇数的有多少种,当然,后面的也得合法,如此,题目就简单了许多...
代码有注释:
#include <bits/stdc++.h> using namespace std; #define int long long const int N=11,M=(1<<10)+3,T=55; const int mod=1e9+7; int odd[N][N],even[N][N],dp[N][M]; //奇数的i行j列'.'填奇数的种数 偶数的i行j列'.'填偶数的种数 在i行状态为j的种数 bool b_odd[N][N],b_even[N][N]; //判断这个位子是不是有奇数/偶数 char s[T]; signed main() { int h,w,n,m; scanf("%lld%lld%lld%lld",&h,&w,&n,&m);//输入 for(int i=0;i<n;i++) for(int j=0;j<m;j++) odd[i][j]=even[i][j]=1; for(int i=0;i<h;i++) { scanf("%s",s); for(int j=0;j<w;j++) { if(s[j]=='.') { odd[i%n][j%m]=odd[i%n][j%m]*5%mod; even[i%n][j%m]=even[i%n][j%m]*4%mod; } else if((s[j]-'0')%2)//有奇数 { b_odd[i%n][j%m]=true; } else//有偶数 { b_even[i%n][j%m]=true; } } } //统计完成 for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(b_odd[i][j]&b_even[i][j]) { puts("0"); return 0; } //特判无解. dp[0][0]=1; for(int i=1;i<=n;i++) { for(int j=0;j<(1<<m);j++)//二进制枚举'.'的奇偶 { int sum=1,flag=0,tag=0;//统计答案,直接判断无解的,间接判断无解 for(int k=0;k<m;k++) { if(j&(1<<k))//奇数 { tag^=1; sum=sum*odd[i-1][k]%mod; if(b_even[i-1][k]) {flag=1; break;} } else//偶数 { sum=sum*even[i-1][k]%mod; if(b_odd[i-1][k]) {flag=1; break;} } } if(flag||!tag) continue; for(int l=0;l<(1<<m);l++) dp[i][l^j]=(dp[i][l^j]+dp[i-1][l]*sum)%mod; } } printf("%lld\n",dp[n][(1<<m)-1]); return 0; }