• Leftmost Ball


    题目链接:Click here

    Solution:

    我们把问题转化一下,改成可以放白球和其他颜色的球

    那么对于一种合法的方案,显然有它的任意一个前缀的白球数大于等于其他颜色数

    那么,我们考虑设(f[i][j])表示已经放了(i)个白球,刚好放完了(j)种颜色的方案数

    考虑有两种转移,一种是我们再放一个白球,或者再加入一种颜色

    这里我们钦定接下来放的第一个球一定在第一个空缺的位置,否则就会算重

    那么转移就是这样的:

    [f[i][j]=f[i-1][j]+f[i][j-1] imes {(k-1) imes (n-j+1)+n-i-1 choose k-2} ]

    需要注意的是,当(k=1)时,我们需要给出特判,并且我们在(dp)时是没有考虑颜色的排列顺序的,所以最后要乘上阶乘

    Code:

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=2e3+11;
    const int M=4e6+11;
    const int mod=1e9+7;
    int n,k,f[N][N],fac[M],ifac[M];
    int read(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
        while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
        return x*f;
    }
    int qpow(int a,int b){
        int re=1;
        while(b){
            if(b&1) re=(re*a)%mod;
            b>>=1;a=a*a%mod;
        }return re;
    }
    int C(int a,int b){
        if(a<b) return 0;
        return fac[a]*ifac[b]%mod*ifac[a-b]%mod;
    }
    signed main(){
        n=read(),k=read();
        if(k==1) return puts("1"),0;
        fac[0]=1;ifac[0]=1;f[0][0]=1;
        for(int i=1;i<=n*k;i++) fac[i]=fac[i-1]*i%mod;
        ifac[n*k]=qpow(fac[n*k],mod-2);
        for(int i=n*k-1;i;i--) ifac[i]=ifac[i+1]*(i+1)%mod;
        for(int i=1;i<=n;i++)
            for(int j=0;j<=i;j++){
                if(i>j) f[i][j]+=f[i-1][j];
                f[i][j]=(f[i][j]+f[i][j-1]*C((n-j+1)*(k-1)+n-i-1,k-2)%mod)%mod;
            }
        printf("%lld
    ",f[n][n]*fac[n]%mod);
        return 0;
    }
    
  • 相关阅读:
    Android 高仿微信支付密码输入控件
    ListView用法总结
    我的感悟
    Android Scroll分析——滑动效果产生
    如何查看Android的Keystore文件的SHA1值
    Android 事件拦截机制一种粗鄙的解释
    Android 自定义ViewGroup
    Android 自定义View 总结
    Android 自定义View 三板斧之三——重写View来实现全新控件
    Android 自定义View 三板斧之二——组合现有控件
  • 原文地址:https://www.cnblogs.com/NLDQY/p/12214807.html
Copyright © 2020-2023  润新知