/* Things to notice: 1. do not calculate useless values 2. do not use similar names Things to check: 1. submit the correct file 2. time (it is log^2 or log) 3. memory 4. prove your naive thoughts 5. long long 6. corner case like n=0,1,inf or n=m 7. check if there is a mistake in the ds or other tools you use 8. fileio in some oi-contest 9. module on time 10. the number of a same divisor in a math problem 11. multi-information and queries for dp and ds problems */ #include<bits/stdc++.h> using namespace std; #define ll long long #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back const int mod=1e9+7; const int inf=0x3f3f3f3f; int fpow(int x,int b) { if(x==0) return 0; if(b==0) return 1; int res=1; while(b>0) { if(b&1) res=1LL*res*x%mod; x=1LL*x*x%mod; b>>=1; } return res; } int C[105][105]; void add(int &x,int y) { x+=y; if(x>=mod) x-=mod; } int n,m,K; int id[33][33],uidx; int dp[2][565][1455][71],f[565][1455][151]; int g[205],h[205]; const int D1=720; const int D2=35; const int D3=70; int adddig[25],addsum; void solve() { C[0][0]=1; for(int i=1;i<=100;i++) { C[i][0]=1; for(int j=1;j<=i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; } cin>>n>>m>>K; for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) if(i+j<=n) id[i][j]=uidx++; for(int i=1;i<=K;i++) { string s; cin>>s; int tag=(s[0]=='C'?1:-1); if(tag==-1) for(int j=0;j<m;j++) s[j]=(s[j]=='C'?'N':'C'); int sp=s.size(); for(int j=0;j<s.size();j++) if(s[j]!=s[0]) { sp=j; break; } if(sp==s.size()) { addsum+=tag*s.size(); continue; } addsum+=tag*(sp-1); s+='C'; for(int j=sp+1;j<s.size();j++) if(s[j]=='C') adddig[j-sp-1]+=tag; } // cout<<addsum<<"\n"; // for(int j=0;j<=m;j++) cout<<adddig[j]<<" "; // cout<<"\n"; for(int cp=0;cp<=n-K;cp++) for(int cn=0;cn+cp<=n-K;cn++) if((cp-cn+adddig[m-2])%2==0) add(dp[0][id[cp][cn]][D1][(cp-cn+adddig[m-2])/2+D2],C[cp+cn][cn]);//,cout<<cp<<" "<<cn<<" "<<(cp-cn+adddig[m-2])/2<<"\n"; int nw=0; for(int i=m-3;i>=0;i--) { nw^=1; memset(dp[nw],0,sizeof(dp[nw])); memset(f,0,sizeof(f)); for(int cp=0;cp<=n-K;cp++) for(int cn=0;cp+cn<=n-K;cn++) for(int s=(-cn)*(m-2-i);s<=cp*(m-2-i);s++) { memset(g,0,sizeof(g)); for(int car=-n;car<=n;car++) if(dp[nw^1][id[cp][cn]][s+D1][car+D2]) { for(int del=0;del<=cp;del++) add(g[car+del+D3],1LL*dp[nw^1][id[cp][cn]][s+D1][car+D2]*C[cp][del]%mod); } memset(h,0,sizeof(h)); for(int car=-n;car<=2*n;car++) if(g[car+D3]) { for(int del=0;del<=cn;del++) add(h[car-del+D3],1LL*g[car+D3]*C[cn][del]%mod); } for(int car=-2*n;car<=2*n;car++) if(h[car+D3]) { for(int dcp=0;dcp+cp+cn<=n-K;dcp++) //for(int dcn=0;dcn+cn+dcp+cp<=n-K;dcn++) if((car+dcp-dcn+adddig[i])%2==0) { add(f[id[cp+dcp][cn]][s+dcp*(m-2-i)+D1][(car+dcp)+D3],1LL*h[car+D3]*C[cp+dcp+cn][dcp]%mod); // cout<<cp<<" "<<cn<<" "<<s<<" "<<car<<" -> "<<cp+dcp<<" "<<cn+dcn<<" "<<s+(dcp-dcn)*(m-2-i)<<" "<<(car+dcp-dcn+adddig[i])/2<<" "<<1LL*h[car+D3]*C[cp+dcp+cn+dcn][dcp+dcn]%mod*C[dcp+dcn][dcp]%mod<<"\n"; // add(dp[nw][id[cp+dcp][cn+dcn]][s+(dcp-dcn)*(m-2-i)+D1][(car+dcp-dcn+adddig[i])/2+D2],1LL*h[car+D3]*C[cp+dcp+cn+dcn][dcp+dcn]%mod*C[dcp+dcn][dcp]%mod); } } } for(int cp=0;cp<=n-K;cp++) for(int cn=0;cp+cn<=n-K;cn++) for(int s=(-cn)*(m-2-i);s<=cp*(m-2-i);s++) for(int car=-2*n;car<=2*n;car++) if(f[id[cp][cn]][s+D1][car+D3]) { for(int dcn=0;dcn+cp+cn<=n-K;dcn++) if((car-dcn+adddig[i])%2==0) add(dp[nw][id[cp][cn+dcn]][s-dcn*(m-2-i)+D1][(car-dcn+adddig[i])/2+D2],1LL*f[id[cp][cn]][s+D1][car+D3]*C[cp+dcn+cn][dcn]%mod); } // cerr<<i<<"\n"; } for(int i=0;i<=n-K;i++) { int ans=0; for(int cp=0;cp<=i;cp++) for(int cn=0;cp+cn<=i;cn++) for(int s=(-cn)*(m-2);s<=cp*(m-2);s++) for(int car=-n;car<=n;car++) if(dp[nw][id[cp][cn]][s+D1][car+D2]) { // cout<<i<<": "<<cp<<" "<<cn<<" "<<s<<" "<<car<<"\n"; int x=s+car+addsum; x=-x; if(x%m) continue; int c1=x/m,c2=i-cp-cn; int dcp=(c1+c2)/2,dcn=(c2-c1)/2; // cout<<i<<": "<<cp<<" "<<cn<<" "<<s<<" "<<car<<" "<<dcp<<" "<<dcn<<"\n"; if((-x)+dcp*m-dcn*m!=0||cp+cn+dcp+dcn!=i||dcp<0||dcn<0) continue; // cout<<i<<": "<<cp<<" "<<cn<<" "<<s<<" "<<car<<" "<<dcp<<" "<<dcn<<"\n"; add(ans,1LL*dp[nw][id[cp][cn]][s+D1][car+D2]*C[cp+dcp+cn+dcn][dcp+dcn]%mod*C[dcp+dcn][dcp]%mod); } cout<<ans<<" "; } } signed main() { ios::sync_with_stdio(0); cin.tie(0); int _=1; // cin>>_; while(_--) solve(); return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | /* Things to notice: 1. do not calculate useless values 2. do not use similar names Things to check: 1. submit the correct file 2. time (it is log^2 or log) 3. memory 4. prove your naive thoughts 5. long long 6. corner case like n=0,1,inf or n=m 7. check if there is a mistake in the ds or other tools you use 8. fileio in some oi-contest 9. module on time 10. the number of a same divisor in a math problem 11. multi-information and queries for dp and ds problems */ #include<bits/stdc++.h> using namespace std; #define ll long long #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back const int mod=1e9+7; const int inf=0x3f3f3f3f; int fpow(int x,int b) { if(x==0) return 0; if(b==0) return 1; int res=1; while(b>0) { if(b&1) res=1LL*res*x%mod; x=1LL*x*x%mod; b>>=1; } return res; } int C[105][105]; void add(int &x,int y) { x+=y; if(x>=mod) x-=mod; } int n,m,K; int id[33][33],uidx; int dp[2][565][1455][71],f[565][1455][151]; int g[205],h[205]; const int D1=720; const int D2=35; const int D3=70; int adddig[25],addsum; void solve() { C[0][0]=1; for(int i=1;i<=100;i++) { C[i][0]=1; for(int j=1;j<=i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; } cin>>n>>m>>K; for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) if(i+j<=n) id[i][j]=uidx++; for(int i=1;i<=K;i++) { string s; cin>>s; int tag=(s[0]=='C'?1:-1); if(tag==-1) for(int j=0;j<m;j++) s[j]=(s[j]=='C'?'N':'C'); int sp=s.size(); for(int j=0;j<s.size();j++) if(s[j]!=s[0]) { sp=j; break; } if(sp==s.size()) { addsum+=tag*s.size(); continue; } addsum+=tag*(sp-1); s+='C'; for(int j=sp+1;j<s.size();j++) if(s[j]=='C') adddig[j-sp-1]+=tag; } // cout<<addsum<<"\n"; // for(int j=0;j<=m;j++) cout<<adddig[j]<<" "; // cout<<"\n"; for(int cp=0;cp<=n-K;cp++) for(int cn=0;cn+cp<=n-K;cn++) if((cp-cn+adddig[m-2])%2==0) add(dp[0][id[cp][cn]][D1][(cp-cn+adddig[m-2])/2+D2],C[cp+cn][cn]);//,cout<<cp<<" "<<cn<<" "<<(cp-cn+adddig[m-2])/2<<"\n"; int nw=0; for(int i=m-3;i>=0;i--) { nw^=1; memset(dp[nw],0,sizeof(dp[nw])); memset(f,0,sizeof(f)); for(int cp=0;cp<=n-K;cp++) for(int cn=0;cp+cn<=n-K;cn++) for(int s=(-cn)*(m-2-i);s<=cp*(m-2-i);s++) { memset(g,0,sizeof(g)); for(int car=-n;car<=n;car++) if(dp[nw^1][id[cp][cn]][s+D1][car+D2]) { for(int del=0;del<=cp;del++) add(g[car+del+D3],1LL*dp[nw^1][id[cp][cn]][s+D1][car+D2]*C[cp][del]%mod); } memset(h,0,sizeof(h)); for(int car=-n;car<=2*n;car++) if(g[car+D3]) { for(int del=0;del<=cn;del++) add(h[car-del+D3],1LL*g[car+D3]*C[cn][del]%mod); } for(int car=-2*n;car<=2*n;car++) if(h[car+D3]) { for(int dcp=0;dcp+cp+cn<=n-K;dcp++) //for(int dcn=0;dcn+cn+dcp+cp<=n-K;dcn++) if((car+dcp-dcn+adddig[i])%2==0) { add(f[id[cp+dcp][cn]][s+dcp*(m-2-i)+D1][(car+dcp)+D3],1LL*h[car+D3]*C[cp+dcp+cn][dcp]%mod); // cout<<cp<<" "<<cn<<" "<<s<<" "<<car<<" -> "<<cp+dcp<<" "<<cn+dcn<<" "<<s+(dcp-dcn)*(m-2-i)<<" "<<(car+dcp-dcn+adddig[i])/2<<" "<<1LL*h[car+D3]*C[cp+dcp+cn+dcn][dcp+dcn]%mod*C[dcp+dcn][dcp]%mod<<"\n"; // add(dp[nw][id[cp+dcp][cn+dcn]][s+(dcp-dcn)*(m-2-i)+D1][(car+dcp-dcn+adddig[i])/2+D2],1LL*h[car+D3]*C[cp+dcp+cn+dcn][dcp+dcn]%mod*C[dcp+dcn][dcp]%mod); } } } for(int cp=0;cp<=n-K;cp++) for(int cn=0;cp+cn<=n-K;cn++) for(int s=(-cn)*(m-2-i);s<=cp*(m-2-i);s++) for(int car=-2*n;car<=2*n;car++) if(f[id[cp][cn]][s+D1][car+D3]) { for(int dcn=0;dcn+cp+cn<=n-K;dcn++) if((car-dcn+adddig[i])%2==0) add(dp[nw][id[cp][cn+dcn]][s-dcn*(m-2-i)+D1][(car-dcn+adddig[i])/2+D2],1LL*f[id[cp][cn]][s+D1][car+D3]*C[cp+dcn+cn][dcn]%mod); } // cerr<<i<<"\n"; } for(int i=0;i<=n-K;i++) { int ans=0; for(int cp=0;cp<=i;cp++) for(int cn=0;cp+cn<=i;cn++) for(int s=(-cn)*(m-2);s<=cp*(m-2);s++) for(int car=-n;car<=n;car++) if(dp[nw][id[cp][cn]][s+D1][car+D2]) { // cout<<i<<": "<<cp<<" "<<cn<<" "<<s<<" "<<car<<"\n"; int x=s+car+addsum; x=-x; if(x%m) continue; int c1=x/m,c2=i-cp-cn; int dcp=(c1+c2)/2,dcn=(c2-c1)/2; // cout<<i<<": "<<cp<<" "<<cn<<" "<<s<<" "<<car<<" "<<dcp<<" "<<dcn<<"\n"; if((-x)+dcp*m-dcn*m!=0||cp+cn+dcp+dcn!=i||dcp<0||dcn<0) continue; // cout<<i<<": "<<cp<<" "<<cn<<" "<<s<<" "<<car<<" "<<dcp<<" "<<dcn<<"\n"; add(ans,1LL*dp[nw][id[cp][cn]][s+D1][car+D2]*C[cp+dcp+cn+dcn][dcp+dcn]%mod*C[dcp+dcn][dcp]%mod); } cout<<ans<<" "; } } signed main() { ios::sync_with_stdio(0); cin.tie(0); int _=1; // cin>>_; while(_--) solve(); return 0; } |