ARC102E Stop. Otherwise...
题面:Atcoder
解析
题意即让为每一个骰子选一个点数,使不存在两个骰子点数和为(x)的方案数。
考虑容斥,设当前组成和为(x)的方案数为(t),(g(i))表示至少有(i)对和为(x)的方案数,那么有:
[ans=sum_{i=0}^{t}(-1)^i g(i)
]
这样得到的答案便是合法的方案数,现在考虑如何计算(g(i)),就是强制选(i)对,然后剩下随意分配即可,那么有:
[g(i)={t choose i}{n-2 imes i+K-1 choose K-1}
]
代码
#include<cstdio>
#define N 2005
using namespace std;
const int P=998244353,__=4000;
inline int In(){
char c=getchar(); int x=0,ft=1;
for(;c<'0'||c>'9';c=getchar()) if(c=='-') ft=-1;
for(;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
return x*ft;
}
int K,n,ans[N],fac[N*2],inv[N*2];
inline int power(int x,int k){
int s=1,t=x;
for(;k;k>>=1,t=1ll*t*t%P) if(k&1) s=1ll*s*t%P;
return s;
}
inline int C(int m,int n){
return 1ll*fac[m]*inv[n]%P*inv[m-n]%P;
}
int main(){
K=In(); n=In();
fac[0]=1; for(int i=1;i<=__;++i) fac[i]=1ll*fac[i-1]*(i)%P;
inv[__]=power(fac[__],P-2); for(int i=__-1;~i;--i) inv[i]=1ll*inv[i+1]*(i+1)%P;
for(int i=2,t;i<=K+1;++i){
t=i/2;
for(int j=0,d=1;2*j<=n&&j<=t;++j,d=P-d)
(ans[i]+=1ll*d*C(t,j)%P*C(n-2*j+K-1,K-1)%P)%=P;
printf("%d
",ans[i]);
}
for(int i=K;i>=2;--i) printf("%d
",ans[i]);
return 0;
}