Leftmost Ball

Posted nldqy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

以上是关于Leftmost Ball的主要内容,如果未能解决你的问题,请参考以下文章

AGC002F Leftmost Ball

AT2000 Leftmost Ball

「AtCoder AGC002F」Leftmost Ball

[AGC002F]Leftmost Ball

AtCoder Grand Contest 002 (AGC002) F - Leftmost Ball 动态规划 排列组合

var ball0=new Ball("executing") 是怎样被执行的?