【AtCoder2000】Leftmost Ball (DP+组合数)

本文探讨了Snuke对彩色球进行特定排列并重新着色的问题,通过动态规划的方法来计算不同排列方案的数量,并给出了具体的算法实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意

Snuke喜欢五颜六色的球。他总共有N×K个球,有N种颜色,每种颜色的球有K个。颜色编号为1到N。他将按照任意顺序排列所有球。然后,对于每种颜色,他将该颜色的最左边的球涂成颜色0,颜色0不同于N种原始颜色中的任何颜色。如将球排列为(1,2,1,2),染色后就变为 (0,0,1,2)。
所有操作后,球的颜色序列有多少种,求这个方案数mod 10^9+7。

题解

发现一个性质:对任何前缀,0的个数必须出现的其它颜色种类数
可定义dp[i][j]dp[i][j]表示有i个0,j种颜色都已经放完的方案数
转移:
新放了一个0
dp[i][j]+=dp[i1][j]dp[i][j]+=dp[i−1][j]
新放了一种颜色,这个颜色的第一个球必须放在最开始(表示这时候已经出现过这种颜色),(还有一个球变为了0)这种颜色还剩下K2K−2个球可以随便放,则需乘上组合数
dp[i][j]+=dp[i][j1]×CK2N×Ki(j1)(K1)1dp[i][j]+=dp[i][j−1]×CN×K−i−(j−1)(K−1)−1K−2
最后答案为dp[N][N]×N!dp[N][N]×N!(dp时没有考虑颜色的区别,还需乘上颜色的排列数)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=2005,MOD=1000000007;

int PowMod(int a,int b)
{
    int ret=1;
    while(b)
    {
        if(b&1)
            ret=1LL*ret*a%MOD;
        a=1LL*a*a%MOD;
        b>>=1;
    }
    return ret;
}

int fac[MAXN*MAXN],ifac[MAXN*MAXN];

void Init()
{
    fac[0]=1;
    for(int i=1;i<MAXN*MAXN;i++)
        fac[i]=1LL*fac[i-1]*i%MOD;
    ifac[MAXN*MAXN-1]=PowMod(fac[MAXN*MAXN-1],MOD-2);
    for(int i=MAXN*MAXN-2;i>=0;i--)
        ifac[i]=1LL*ifac[i+1]*(i+1)%MOD;
}
int C(int n,int r)
{return 1LL*fac[n]*ifac[n-r]%MOD*ifac[r]%MOD;}

int N,K,dp[MAXN][MAXN];

int main()
{
    Init();
    scanf("%d%d",&N,&K);
    if(K==1)
    {
        puts("1");
        return 0;
    }
    dp[0][0]=1;
    for(int i=0;i<=N;i++)
        for(int j=0;j<=i;j++)
        {
            if(i)
                dp[i][j]=(dp[i][j]+dp[i-1][j])%MOD;
            if(j)
                dp[i][j]=(dp[i][j]+1LL*dp[i][j-1]*C(N*K-i-(K-1)*(j-1)-1,K-2)%MOD)%MOD;
        }
    int ans=1LL*dp[N][N]*fac[N]%MOD;
    printf("%d\n",ans);

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CaptainHarryChen

随便

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值