zoukankan      html  css  js  c++  java
  • 【agc002f】Leftmost Ball

    题目大意

    有n种颜色,每种k个球。将这些球任意排列,将每种颜色中最前面的一个求涂成白色(就是n+1种颜色),求最终的排列的方案的个数。

    解题思路

    考虑如何计算不会算重,
    按颜色顺序,每次往排列插入k个球,k-1个某种颜色,以及一个白球。
    那么只要我们每次插入k个球时,保证白球一定在之前插入的白球的后面,并且某种颜色的第一个球,放在上一次的颜色的第一个球的后面,就可以保证不会算重,最后再乘个n!。
    但是正着不好做,于是反过来插入,先插的n种颜色,dp一下,设f[i][j]表示放到第i种颜色,前面有j+1个白球(为啥是j+1?其实只是为了方便)。

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <bitset>
    #include <set>
    const int maxlongint=2147483647;
    const long long mo=1e9+7;	
    const int N=2005;
    using namespace std;
    int n,k;
    long long f[N][N],jc[N*N],ny[N*N],ans;
    long long poww(long long x,int y)
    {
    	long long s=1;
    	for(;y;y>>=1,x=x*x%mo)
    		if(y&1) s=s*x%mo;
    	return s;
    }
    long long C(int m,int n)
    {
    	if(n>m) return 0;
    	return jc[m]*ny[n]%mo*ny[m-n]%mo;
    }
    int main()
    {
    	scanf("%d%d",&n,&k);
    	if(k<=1)
    	{
    		printf("1
    ");
    		return 0;
    	}
    	jc[0]=ny[0]=1;
    	for(int i=1;i<=n*k;i++) jc[i]=jc[i-1]*i%mo,ny[i]=poww(jc[i],mo-2);
    	f[0][0]=1;
    	for(int i=1;i<=n;i++)
    		for(int j=i;j>=0;j--)
    			f[i][j]=(f[i][j]+f[i-1][j-1]*C(k*i-j-1,k-2)%mo+f[i][j+1])%mo;
    	printf("%lld",f[n][0]*jc[n]%mo);
    }
    
  • 相关阅读:
    docker搭建本地仓库并制作自己的镜像
    docker命令及操作
    从零开始学android开发-项目打包发布
    从零开始学android开发-adt-bundle-eclipse下的修改android app名称
    从零开始学android开发-项目重命名
    Android Studio系列教程一--下载与安装
    Axure RP 7.0注册码
    MVC网站发布常见问题
    无间断滚动的新闻文章列表
    @HTML
  • 原文地址:https://www.cnblogs.com/chen1352/p/9099505.html
Copyright © 2011-2022 走看看