• 【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);
    }
    
  • 相关阅读:
    从0移植uboot (一) _配置分析
    一段美好的记忆,一份真挚的感情,已经远去......
    搭建SSH服务
    Ubuntu16.04中搭建TFTP 和 NFS 服务器
    关于x210开发板和主机、虚拟机ping通问题
    SPI总线的特点、工作方式及常见错误解答
    u-boot全面分析
    C语言类型的隐式转换问题
    uboot-jiuding 下主Makefile详解
    异常处理
  • 原文地址:https://www.cnblogs.com/chen1352/p/9099505.html
Copyright © 2020-2023  润新知