#include<iostream>#include<cstdio>constlonglong mod =998244353;usingnamespace std ;int n , m ;int a[105][2005];int cnt[2005];longlong ans ;voidinput(){scanf("%d%d",&n ,&m);for(int i =1; i <= n ; i++){for(int j =1; j <= m ; j++){scanf("%d",&a[i][j]);}}}voiddfs(int x ,longlong sum){if( x > n ){longlong num =0;for(int i =1; i <= m ; i++){
num += cnt[i];}
num /=2;for(int i =1; i <= m ; i++){if( cnt[i]> num )return;}
ans += sum ;
ans = ans % mod ;return;}dfs(x +1, sum);for(int i =1; i <= m ; i++){if( a[x][i]==0)continue;
cnt[i]++;dfs(x +1, sum * a[x][i]% mod);
cnt[i]--;}}intmain(){input();dfs(1,1);printf("%lld\n", ans -1);return0;}
#include<iostream>#include<cstdio>constlonglong mod =998244353;usingnamespace std ;int n , m ;int a[105][2005];int cnt[2005];longlong ans ;longlong dp[105][55][55];voidinput(){scanf("%d%d",&n ,&m);for(int i =1; i <= n ; i++){for(int j =1; j <= m ; j++){scanf("%d",&a[i][j]);}}}voiddfs(int x ,longlong sum){if( x > n ){longlong num =0;for(int i =1; i <= m ; i++){
num += cnt[i];}
num /=2;for(int i =1; i <= m ; i++){if( cnt[i]> num )return;}
ans += sum ;
ans = ans % mod ;return;}dfs(x +1, sum);for(int i =1; i <= m ; i++){if( a[x][i]==0)continue;
cnt[i]++;dfs(x +1, sum * a[x][i]% mod);
cnt[i]--;}}intmain(){input();if( n <=10){dfs(1,1);printf("%lld\n", ans -1);return0;}if( m ==2){
ans =0;
dp[0][0][0]=1;for(int i =1; i <= n ; i++){for(int j =0; j <= n /2; j++){for(int k =0; k <= n /2; k++){
dp[i][j][k]= dp[i -1][j][k];if( j >0){
dp[i][j][k]=(dp[i][j][k]+(dp[i -1][j -1][k]* a[i][1])% mod)% mod ;}if( k >0){
dp[i][j][k]=(dp[i][j][k]+(dp[i -1][j][k -1]* a[i][2])% mod)% mod ;}}}}for(int i =1; i <= n /2; i++){
ans =( ans + dp[n][i][i])% mod ;}printf("%lld\n", ans);return0;}return0;}
m = 3(64pts)
由m = 2的dp想到m = 3也可用dp,开四维处理即可
直接dp一下即可
代码几乎与m = 2相同
#include<iostream>#include<cstdio>constlonglong mod =998244353;usingnamespace std ;int n , m ;int a[105][2005];int cnt[2005];longlong ans ;longlong dp[105][55][55];longlong dp2[105][55][55][55];voidinput(){scanf("%d%d",&n ,&m);for(int i =1; i <= n ; i++){for(int j =1; j <= m ; j++){scanf("%d",&a[i][j]);}}}voiddfs(int x ,longlong sum){if( x > n ){longlong num =0;for(int i =1; i <= m ; i++){
num += cnt[i];}
num /=2;for(int i =1; i <= m ; i++){if( cnt[i]> num )return;}
ans += sum ;
ans = ans % mod ;return;}dfs(x +1, sum);for(int i =1; i <= m ; i++){if( a[x][i]==0)continue;
cnt[i]++;dfs(x +1, sum * a[x][i]% mod);
cnt[i]--;}}intmain(){input();if( n <=10){dfs(1,1);printf("%lld\n", ans -1);return0;}if( m ==2){
ans =0;
dp[0][0][0]=1;for(int i =1; i <= n ; i++){for(int j =0; j <= n /2; j++){for(int k =0; k <= n /2; k++){
dp[i][j][k]= dp[i -1][j][k];if( j >0){
dp[i][j][k]=(dp[i][j][k]+(dp[i -1][j -1][k]* a[i][1])% mod)% mod ;}if( k >0){
dp[i][j][k]=(dp[i][j][k]+(dp[i -1][j][k -1]* a[i][2])% mod)% mod ;}}}}for(int i =1; i <= n /2; i++){
ans =( ans + dp[n][i][i])% mod ;}printf("%lld\n", ans);return0;}elseif( m ==3){
dp2[0][0][0][0]=1;for(int i =1; i <= n ; i++)for(int j =0; j <= n; j++)for(int k =0; k <= i - j ; k++)for(int l =0; l <= i - j - k ; l++){
dp2[ i ][ j ][ k ][ l ]=
dp2[ i -1][ j ][ k ][ l ];if( j >=1)
dp2[ i ][ j ][ k ][ l ]+=
dp2[ i -1][ j -1][ k ][ l ]*
a[ i ][1]% mod ;if( k >=1)
dp2[ i ][ j ][ k ][ l ]+=
dp2[ i -1][ j ][ k -1][ l ]*
a[ i ][2]% mod ;if( l >=1)
dp2[ i ][ j ][ k ][ l ]+=
dp2[ i -1][ j ][ k ][ l -1]*
a[ i ][3]% mod ;}for(int i =0; i <= n /2; i++)for(int j =0; j <= n /2; j++)for(int k =0; k <= n /2; k++){if( i <= j + k && j <= i + k && k <= i + j )
ans += dp2[ n ][ i ][ j ][ k ];
ans = ans % mod ;}printf("%lld\n", ans -1);}return0;}
#include<iostream>#include<cstdio>#include<cstring>usingnamespace std ;constint mod =998244353;constint N =2100;int n , m ;int x[105][2005];longlong sum[105];longlong a[2005], b[2005];longlong dp[105][105][105];voidinput(){scanf("%d%d",&n ,&m);for(int i =1; i <= n ; i++){for(int j =1; j <= m ; j++){scanf("%d",&x[i][j]);}}return;}voiddoit(){longlong tot =1;for(int i =1; i <= n ; i++){
sum[i]=0;for(int j =1; j <= m ; j++){
sum[i]+= x[i][j];
sum[i]%= mod ;}
tot =( tot *( sum[i]+1))% mod ;}longlong wrong =0;for(int food =1; food <= m ; food++){memset(dp ,0,sizeof(dp));for(int i =1; i <= n ; i++)
a[i]= x[i][food], b[i]=(sum[i]- a[i]+ mod)% mod ;
dp[0][0][0]=1;for(int i =1; i <= n ; i++)for(int j =0; j <= i ; j++)for(int k =0; k <= i - j ; k++){
dp[i][j][k]= dp[i -1][j][k];if( j >0){
dp[i][j][k]=(dp[i][j][k]+(dp[i -1][j -1][k]* a[i])% mod)% mod ;}if( k >0){
dp[i][j][k]=(dp[i][j][k]+(dp[i -1][j][k -1]* b[i])% mod)% mod ;}}for(int i =1; i <= n ; i++)for(int j =0; j <= n - i ; j++)if( i > j )
wrong += dp[n][i][j];
wrong %= mod ;}printf("%lld\n",(tot -1- wrong + mod)% mod);}intmain(){input();doit();return0;}
#include<iostream>#include<cstdio>#include<cstring>usingnamespace std ;constint mod =998244353;constint N =2100;int n , m ;int x[105][2005];longlong sum[105];longlong a[2005], b[2005];longlong dp[105][2105];voidinput(){scanf("%d%d",&n ,&m);for(int i =1; i <= n ; i++){for(int j =1; j <= m ; j++){scanf("%d",&x[i][j]);}}return;}voiddoit(){longlong tot =1;for(int i =1; i <= n ; i++){
sum[i]=0;for(int j =1; j <= m ; j++){
sum[i]+= x[i][j];
sum[i]%= mod ;}
tot =( tot *( sum[i]+1))% mod ;}longlong wrong =0;for(int food =1; food <= m ; food++){memset(dp ,0,sizeof(dp));for(int i =1; i <= n ; i++)
a[i]= x[i][food], b[i]=(sum[i]- a[i]+ mod)% mod ;
dp[0][N]=1;for(int i =1; i <= n ; i++){for(int j =-1* i ; j <= i ; j++){
dp[i][N + j]= dp[i -1][N + j];if( N + j -1>=0)
dp[i][N + j]+=( dp[i -1][N + j -1]* a[i]% mod );
dp[i][N + j]+=( dp[i -1][N + j +1]* b[i]% mod );
dp[i][N + j]%= mod ;}}for(int i =1; i <= n ; i++)
wrong += dp[n][N + i];
wrong %= mod ;}printf("%lld\n",(tot -1- wrong + mod)% mod);}intmain(){input();doit();return0;}
纯暴力(32 pts)开始的第一思路,可以过测试点1-8直接枚举出每种烹饪方法所用的主要食材用搜索枚举,传入两个参数:现在枚举的烹饪方法编号以及在此之前的方案数代码:#include <iostream>#include <cstdio>const long long mod = 998244353 ;using namespace std ;...