CF1188E Problem from Red Panda

cf

我們可以把題目中的選擇\(k-1\)種顏色,並且全部改成剩下那種顏色改爲選擇一種顏色的球增加\(k\)個,然後所有顏色的球減少\(1\)

然後考慮一個狀態\(b\)能否在第\(x\)輪到達.對於每一位\(i\),需要在之前操作中選擇\(\frac{b_i-(a_i-x)}{k}\)次纔可以到達(注意這裏的次數要是整數,否則不合法).再根據題目的一些條件,可以發現經過\(x\)輪能到達\(b\)狀態當且僅當

  • \(\forall i,k|(b_i-(a_i-x))\)\(\sum_{i=1}^{k}\frac{b_i-(a_i-x)}{k}=x\)
  • 過程中所有的\(a_i\)要爲非負整數

條件2可以推出對於一個\(a_i\),必須在前\(a_i+1\)輪內對\(i\)加一次\(k\).同理,要在前\(a_i+k+1\)輪內對\(i\)加兩次\(k\),要在前\(a_i+2k+1\)輪內對\(i\)加三次\(k\)...依此類推

由於每輪只能給一個顏色\(i\)\(k\),所以隨着輪數的增加,我們必須要用一些輪去給某些\(i\)\(k\)來保持非負,如果對於\(x\)輪可以操作到,且在\(x+1\)輪時,前\(x+1\)的輪都不夠做完前面所有顏色\(i\)所必要的加\(k\)次數了,那麼也就意味着\(x\)輪爲最多能操作的輪數,並且可以發現如果\(x\)是有限的,那麼一定滿足\(x<k\),因爲給一個數加\(k\)後,至少後\(k\)輪都不必要再加\(k\),也就是在滿足操作輪數儘可能多的情況下一個數在\(k\)輪內只會被加一次,如果出現不滿足的情況,那麼一定沒有一個\(i\)加了超過\(1\)\(k\)

然後考慮輪數有限的情況下的方案.枚舉總共操作輪數\(x\),我們可以發現不管給某個顏色\(i\)加多少次\(k\),這個當前的\(a_i'\)和初始\(a_i\)一定滿足\(a_i-a_i'\equiv x\pmod {k}\),也就是輪數有限的情況下每種操作輪數後得到的狀態一定兩兩不同.那麼設\(x\)輪要執行\(c_x\)次必要的加\(k\)操作,剩下操作的可以任意分配給每個\(i\),可以發現這裏操作不用考慮順序,且操作出的狀態只和給每種顏色分配的次數有關且一一對應,方案數就可以寫成\(\binom{x-c_x+k-1}{k-1}\)

還有可能可以操作無限次.我們可以由前面的一些性質推導出\(x\bmod k\)不同的\(x\)得到的狀態不會算重.反之,\(x\bmod k\)相同的狀態是會算重的,不過可以發現\(x\)更小的狀態一定會在\(x\)更大的狀態算重,因爲這個操作是無限輪的,那麼你用這兩個\(x\)之間相差的\(pk\)輪分別給每個顏色加\(p\)次從而得到一樣的狀態.所以對於每個\(j\in[0,k)\),我們只要在一個儘量大的\(x\)(滿足\(k|(x-j)\))處給答案加上\(\binom{x-c_x+k-1}{k-1}\)即可,大概在\(1e6\)及更大的數左右取(因爲再往後走\(x-c_x\)會是一個定值,即不會有其他的新狀態)

#include<bits/stdc++.h>
#define LL long long
#define uLL unsigned long long

using namespace std;
const int N=2e6+10,mod=998244353;
int rd()
{
    int x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();}
    return x*w;
}
void ad(int &x,int y){x+=y,x-=x>=mod?mod:0;}
int fpow(int a,int b){int an=1;while(b){if(b&1) an=1ll*an*a%mod;a=1ll*a*a%mod,b>>=1;}return an;}
int ginv(int a){return fpow(a,mod-2);}
int n,m,mx,a[N],c[N],b[N],fac[N],iac[N];
int C(int a,int b){return b<0||a<b?0:1ll*fac[a]*iac[b]%mod*iac[a-b]%mod;}

int main()
{
    fac[0]=1;
    for(int i=1;i<=N-5;++i) fac[i]=1ll*fac[i-1]*i%mod;
    iac[N-5]=ginv(fac[N-5]);
    for(int i=N-5;i;--i) iac[i-1]=1ll*iac[i]*i%mod;
    n=rd();
    for(int i=1;i<=n;++i)
    {
        a[i]=rd();
        mx=max(mx,a[i]),++c[a[i]];
    }
    for(int i=1,s=0;i<=n;++i)
    {
        s+=c[i-1];
        if(s>i) break;
        ++m;
    }
    int ans=0;
    if(m<n)
    {
        for(int i=0,s=0;i<=m;++i)
        {
            ad(ans,C(i-s+n-1,n-1));
            s+=c[i];
        }
    }
    else
    {
        int s=0;
        for(int i=1;i<=n;++i)
        {
            s+=max((mx-1-a[i]+n)/n,0);
            if(a[i]!=mx) ++b[a[i]%n];
        }
        for(int i=n,j=mx;i;--i,--j)
        {
            ad(ans,C(j-s+n-1,n-1));
            s-=b[(j+n-1)%n],b[(j+n-1)%n]-=j?c[j-1]:0;
        }
    }
    printf("%d\n",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章