Link
将题意进行一些简化:初始有(k)个非负整数,每一轮操作所有的数都会减一,你可以选择一个数使它加(k)。当某个数变为(-1)时无法继续进行操作。
那么假设进行了(x)轮,数的状态为(b),这个状态是合法的当且仅当:
(1.sumlimits_{i=1}^ka_i=sumlimits_{i=1}^kb_i)
(2.kmid b_i-a_i+x)
(3.)过程中(a_i)非负。
显然条件(3)是最不好看的,我们再将其进行转化:
对于第(i)个数(a_i),我们需要在第(a_i+1+nk)轮之前对它进行至少(n+1)次操作。
因此一个很自然的思路是用差分+前缀和维护第(i)轮至少需要进行的操作次数(cnt_i),并求出最多能进行(lim)轮。
如果(lim
e+infty),那么一定有(lim<k)。
因为对于第(i)回合,我只需要复读第(i-k)回合的操作即可做到续命不死。
由此我们也可以推出,若(iequiv jpmod k(i,jle lim)),则第(i,j)轮可能的状态相同,否则一定不同。
先考虑(lim<k)的情况,此时我们只要考虑第(i)轮有多少合法状态。
首先我们必须用掉(cnt_i)次操作,剩下的就相当于是往(k)个不同的盒子里面放(i-cnt_i)个相同的球,可以有空盒的方案数,即({i-cnt_i+k-1choose k-1})。
然后考虑(lim=+infty)的情况。
此时我们只需要取一个足够大的(j)(实际上就是要满足(forall iin[1,k],j>a_i)),然后统计([j,j+k))轮的可能的方案数即可。
#include<cstdio>
#include<cctype>
const int N=2000007,P=998244353,K=1000000;
int fac[N],ifac[N],cnt[N];
int read(){int x=0,c=getchar();while(isspace(c))c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return x;}
void inc(int&a,int b){a+=b-P,a+=a>>31&P;}
int mul(int a,int b){return 1ll*a*b%P;}
int pow(int a,int k){int r=1;for(;k;k>>=1,a=mul(a,a))if(k&1)r=mul(a,r);return r;}
int C(int n,int m){return 1ll*fac[n]*ifac[m]%P*ifac[n-m]%P;}
int main()
{
int k=read(),lim=K+k,ans=0;
for(int i=1,x;i<=k;++i) for(x=read()+1;x<=K+k;++cnt[x],x+=k);
for(int i=1;i<=lim;++i) if((cnt[i]+=cnt[i-1])>i) lim=i-1;
fac[0]=1;for(int i=1;i<=lim+k;++i) fac[i]=mul(fac[i-1],i);
ifac[lim+k]=pow(fac[lim+k],P-2);for(int i=lim+k;i;--i) ifac[i-1]=mul(ifac[i],i);
for(int i=lim;i>lim-k&&~i;--i) inc(ans,C(i-cnt[i]+k-1,k-1));
printf("%d",ans);
}