這個D2T1有點難度啊python
原題:ios
花了我一下午的時間,做爲D2T1的確反常ide
條件很奇怪,感受不太直觀,因而看數據範圍先寫了個暴力優化
寫暴力的時候我就注意到了以前沒有仔細想過的點,烹飪方式必須不一樣spa
雖然a很大,可是n只有100,即總菜數比較小.net
並且雖然m和a都很大,可是一種方法只能作一道菜,即選一種食材設計
因此搜索枚舉每種方法選哪一種食材,最後檢查方案是否知足條件code
這樣能夠拿到32分blog
須要注意到一點很關鍵的性質ci
無論什麼方案,最多隻有一個食材能超過n/2,看到n/2要敏感
那麼若是無視n/2的限制,直接dp就vans了,接下來只須要去掉不合法的方案
枚舉哪種食材超過n/2,能夠發現此時食材只有兩種,枚舉到的食材和其餘的食材
須要表達的狀態數大大減小
設計狀態,f[i][j][k]表示直到第i種方式,總共選了j道菜,其中k道菜用當前枚舉食材
這樣能夠拿到82分
而後就不會了233
這個遞推又沒有決策,咋優化啊
本着單個題目思考時間不能過長的原則,觀摩了python96的題解:
https://blog.csdn.net/weixin_37517391/article/details/103110646
馬上點化233
確實不太好想,果真適時看題解效率更高
咱們記錄狀態的時候沒必要記錄兩類食材的數量,只需記錄兩者差值便可
只要差值相同,不一樣的數量對於合法性的判斷都是等價的
那麼之前的3維dp就優化到2維,能夠ac了
代碼:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 #define LL long long 8 const int mo=998244353; 9 int rd(){int z=0,mk=1; char ch=getchar(); 10 while(ch<'0'||ch>'9'){if(ch=='-')mk=-1; ch=getchar();} 11 while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0'; ch=getchar();} 12 return z*mk; 13 } 14 int n,m,a[110][2100]; 15 LL ans=0; 16 int cnt[2100]; 17 LL s[110]; 18 LL f7[110][110][110]; 19 LL f[110][210]; 20 bool chck(int x){ 21 if(!x) return false; 22 //注意x=0時必須特判,由於此時cnt也全是0,下面條件不會成立 23 for(int i=1;i<=m;++i)if(cnt[i]>x/2) return false; 24 return true; 25 } 26 void dfs(int x,int y,LL z){ 27 if(x==n+1){ 28 if(chck(y)) ans=(ans+z)%mo; 29 return ; 30 } 31 dfs(x+1,y,z); 32 for(int i=1;i<=m;++i)if(a[x][i]){ 33 ++cnt[i]; 34 dfs(x+1,y+1,z*a[x][i]%mo); 35 --cnt[i]; 36 } 37 } 38 LL gan(int x){ 39 memset(f7,0,sizeof(f7)); 40 f7[0][0][0]=1; 41 for(int i=1;i<=n;++i)for(int j=0;j<=i;++j)for(int k=0;k<=j;++k){ 42 f7[i][j][k]=f7[i-1][j][k]; 43 if(j && k) f7[i][j][k]=(f7[i][j][k]+f7[i-1][j-1][k-1]*a[i][x]%mo)%mo; 44 if(j) f7[i][j][k]=(f7[i][j][k]+f7[i-1][j-1][k]*(s[i]-a[i][x])%mo)%mo; 45 } 46 LL bwl=0; 47 for(int i=1;i<=n;++i)for(int j=i/2+1;j<=i;++j) bwl=(bwl+f7[n][i][j])%mo; 48 return bwl; 49 } 50 LL ganisok(int x){ 51 memset(f,0,sizeof(f)); 52 f[0][n]=1; 53 for(int i=1;i<=n;++i)for(int j=0;j<=n+n;++j){ 54 f[i][j]=f[i-1][j]; 55 if(j) f[i][j]=(f[i][j]+f[i-1][j-1]*a[i][x]%mo)%mo; 56 if(j<n+n) f[i][j]=(f[i][j]+f[i-1][j+1]*(s[i]-a[i][x]%mo))%mo; 57 } 58 LL bwl=0; 59 for(int i=n+1;i<=n+n;++i) bwl=(bwl+f[n][i])%mo; 60 return bwl; 61 } 62 int main(){ 63 //freopen("ddd.in","r",stdin); 64 cin>>n>>m; 65 for(int i=1;i<=n;++i)for(int j=1;j<=m;++j) a[i][j]=rd(); 66 if(n<=10 && m<=3){ 67 dfs(1,0,1); 68 cout<<ans<<endl; 69 } 70 else if(n<=40 && m<=500){ 71 for(int i=1;i<=n;++i){ 72 s[i]=0; 73 for(int j=1;j<=m;++j) s[i]=(s[i]+a[i][j])%mo; 74 } 75 LL bwl=1; 76 for(int i=1;i<=n;++i) bwl=bwl*(s[i]+1)%mo; 77 bwl-=1; 78 for(int i=1;i<=m;++i) bwl=(bwl-gan(i))%mo; 79 cout<<(bwl%mo+mo)%mo<<endl; 80 } 81 else{ 82 for(int i=1;i<=n;++i){ 83 s[i]=0; 84 for(int j=1;j<=m;++j) s[i]=(s[i]+a[i][j])%mo; 85 } 86 LL bwl=1; 87 for(int i=1;i<=n;++i) bwl=bwl*(s[i]+1)%mo; 88 bwl-=1; 89 for(int i=1;i<=m;++i) bwl=(bwl-ganisok(i))%mo; 90 cout<<(bwl%mo+mo)%mo<<endl; 91 } 92 return 0; 93 }