ATcoder 2000 Leftmost Ball

Posted 蒟蒻JHY

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ATcoder 2000 Leftmost Ball相关的知识,希望对你有一定的参考价值。

Problem Statement

 

Snuke loves colorful balls. He has a total of N×K balls, K in each of his favorite N colors. The colors are numbered 1 through N.

He will arrange all of the balls in a row from left to right, in arbitrary order. Then, for each of the N colors, he will paint the leftmost ball of that color into color 0, a color different from any of the N original colors.

After painting, how many sequences of the colors of the balls are possible? Find this number modulo 109+7.

Constraints

 

  • 1≤N,K≤2,000

Input

 

The input is given from Standard Input in the following format:

N K

Output

 

Print the number of the possible sequences of the colors of the balls after painting, modulo 109+7.

Sample Input 1

 

2 2

Sample Output 1

 

4

The following 4 sequences are possible:

  • (0,1,0,2)
  • (0,0,1,2)
  • (0,2,0,1)
  • (0,0,2,1)

Sample Input 2

 

3 1

Sample Output 2

 

1

The following 1 sequence is possible:

  • (0,0,0)

Sample Input 3

 

2 3

Sample Output 3

 

14

Sample Input 4

 

2000 2000

Sample Output 4

 

546381702



不妨把0颜色看成白球,把其他颜色看成彩球,那么我们来讨论一下什么样的序列是合法的。
仅有一个序列中的每一个白球都能在其后方匹配到一个是其颜色里出现第一次的彩球,这个序列才合法。
所以我们就可以从后向前dp,状态的定义和转移在代码里都有,只不过特判一下k==1直接输出1就好了。

/*
    f[i][j] 表示 已经出现过 i种颜色的球,
	并且还剩j种颜色的球没有被匹配的方案数。
	
	考虑加入一种新球的话:
	f[i+1][j+1] += f[i][j] * (n-i) * C(k*(i+1)-j-2,k-2) 
	
	考虑加入一种白球的话:
	f[i][j-1] += f[i][j] 
	
	初始化 f[0][0] = 1 
*/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2005;
const int ha=1000000007;
int jc[maxn*maxn],ni[maxn*maxn];
int n,k,f[maxn][maxn];

inline int add(int x,int y){
	x+=y;
	return x>=ha?x-ha:x;
}

inline int ksm(int x,int y){
	int an=1;
	for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha;
	return an;
}

inline void init(){
	jc[0]=1;
	for(int i=1;i<=4004000;i++) jc[i]=jc[i-1]*(ll)i%ha;
	ni[4004000]=ksm(jc[4004000],ha-2);
	for(int i=4004000;i;i--) ni[i-1]=ni[i]*(ll)i%ha;
}

inline int getC(int x,int y){
	return jc[x]*(ll)ni[y]%ha*(ll)ni[x-y]%ha;
}

inline void dp(){
	f[0][0]=1;
	for(int i=0;i<=n;i++)
	    for(int j=i;j>=0;j--) if(f[i][j]){
	    	f[i+1][j+1]=add(f[i+1][j+1],f[i][j]*(ll)(n-i)%ha*(ll)getC(k*(i+1)-j-2,k-2)%ha);
	    	if(j) f[i][j-1]=add(f[i][j-1],f[i][j]);
		}
	
	/*
	for(int i=0;i<=n;i++){
	    for(int j=0;j<=i;j++) printf("%d ",f[i][j]);
	    puts("");
	}
	*/
}

int main(){
	init();
	scanf("%d%d",&n,&k);
	if(k==1) puts("1");
	else{
		dp();
		printf("%d\n",f[n][0]);
	}
	return 0;
}

  

 

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

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

AT2000 Leftmost Ball

Leftmost Digit(hdu1060)(数学题)

ACM_Leftmost Digit

AGC002F Leftmost Ball

Leftmost Digit(数学)