NC54639. [CSP2019]Emiya 家今天的饭(meal)
描述
输入描述
第 1 行两个用单个空格隔开的整数 n,m。
第 2 行至第 n + 1 行,每行 m 个用单个空格隔开的整数,其中第 i + 1 行的 m 个 数依次为 。
输出描述
仅一行一个整数,表示所求方案数对 998,244,353 取模的结果
示例1
输入:
2 3 1 0 1 0 1 1
输出:
3
说明:
由于在这个样例中,对于每组 i, j,Emiya 都最多只会做一道菜,因此我们直接通 过给出烹饪方法、主要食材的编号来描述一道菜。示例2
输入:
3 3 1 2 3 4 5 0 6 0 0
输出:
190
说明:
Emiya 必须至少做 2 道菜。示例3
输入:
5 5 1 0 0 1 1 0 1 0 1 0 1 1 1 1 0 1 0 1 0 1 0 1 1 0 1
输出:
742
C++14(g++5.4) 解法, 执行用时: 103ms, 内存消耗: 1360K, 提交时间: 2019-11-21 12:30:58
#include<bits/stdc++.h> using namespace std; const int M=998244353; int n,m,a[105][2005],i,j,k; long long b[105],f[105][205],ans=1; int main() { // freopen("meal.in","r",stdin); // freopen("meal.out","w",stdout); scanf("%d %d",&n,&m); for(i=1;i<=n;++i) { for(j=1;j<=m;++j) { scanf("%d",&a[i][j]); b[i]=(b[i]+a[i][j])%M; } ans=ans*(b[i]+1)%M; } for(i=1;i<=m;++i) { memset(f,0,sizeof(f)); f[0][n+1]=1; for(j=1;j<=n;++j) for(k=max(-(n/2+1),-j);k<=n&&k<=j;++k) f[j][k+n+1]=(f[j-1][k+n]*a[j][i]+f[j-1][k+n+1]+f[j-1][k+n+2]*(b[j]-a[j][i]))%M; for(j=1;j<=n;++j) ans=(ans-f[n][j+n+1])%M; } cout<<((ans-1)%M+M)%M; }
C++11(clang++ 3.9) 解法, 执行用时: 205ms, 内存消耗: 1252K, 提交时间: 2019-11-17 17:52:26
#include<cstdio> #define M 2001 #define N 101 #define p 998244353 #define ll long long inline int mod(int x){return x>=p?x-p:x;} int a[N][M],f[N<<1],g[N<<1],i,j,k,m,n,s[N],x; int main() { scanf("%d%d",&n,&m),x=1; for(i=1;i<=n;x=(ll)(s[i++]+1)*x%p)for(j=1;j<=m;j++)scanf("%d",a[i]+j),s[i]=mod(s[i]+a[i][j]); for(i=1;i<=m;i++) { for(j=0;j<=n<<1;j++)f[j]=0; for(j=f[n]=1;j<=n;j++) { for(k=1;k<n<<1;k++)g[k-1]=(g[k-1]+(ll)f[k]*a[j][i])%p,g[k+1]=(g[k+1]+(ll)f[k]*(p+s[j]-a[j][i]))%p; for(k=0;k<=n<<1;k++)f[k]=mod(f[k]+g[k]),g[k]=0; } for(j=0;j<n;j++)x=mod(p+x-f[j]); } return 0*printf("%d\n",mod(p+x-1)); }