DELL Software contest 2014 C题 1002 Code Red

题目:

  • Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Others)
Description

When Gary Blauman showed up, Robin totally freaked out because she had no idea he was coming to her wedding. His reply card must be lost in the mail. Robin had planned the seating chart for weeks and Gary Blauman was not in it. The wedding would begin within hours, so she had to ask Marshall for help. It would have been an easy problem, but Marshall happened to find that a few other guests disliked Gary Blauman, which meant that they didn't want to sit on the same table with him.

Before Marshall rearranges the seating chart, he wants to sum up the possible ways to arrange it first.

Input

The input contains more than 1000 test cases and each test case contains a single line, where there are three integer T (2 ≤ T ≤ 1000), G (2 ≤ G ≤ 1000), D (1 ≤ D < G×T), which means there were T tables and there would be G guests sitting on each table and D guests disliked Gary Blauman.

Output

For each test case, output the number of possible ways to arrange the seating chart after module 1234577. Note that tables are distinct, but specific positions of guests on the table are ignored.

Sample Input

2 2 1
2 2 2
2 2 3
3 2 4

Sample Output

4
2
0
18


题意:

有T张桌子,每张桌子能坐G个人,其中有D个人不愿意和Gary Blauman坐,桌子有编号,人也有编号,问有多少种不同的安排方法,答案求模1234577

现场的时候数据各种水,没求模的过了,打个杨辉三角求组合数的过了。。。赛后加强了数据给出


解法:

数论+组合数学


思路:

解是很简单的,就一个简单的组合数学问题,令x为愿意和GB坐的人数,那么有x=T*G-D-1
那么GB的桌子有C(x,y-1)*x,剩下来的人有C(i*y,y)  (i for 1 to x-1),再乘起来就是答案了

但是存在一个问题,C(m,n)要求模,而且组合数的m可能很大,所以无法用杨辉三角打出

所以用逆元来解决

对于a*b = 1 mod p

有c/a = c/a * 1 = c/a * a*b = c*b mod p

b称为a的逆元,如果模数为质数,那么必有逆元

并且逆元满足积性性质

那么问题就可以解决了,预处理首先求出1-y的逆元,再求出1!-y!的逆元,再求出(y!)^x的逆元

求1-y的逆元的时候,可以用exgcd,在数据范围小的时候可以不用,枚举下即可


#include<stdio.h>
#define MOD 1234577
#define N 1005
long long ni[N];
long long k[N][N];
long long fact[N*N];
int main()
{
	long long i,j,t,x,y,z,a,b,ans;
	ni[1]=1;
	for(i=2;i<=1000;i++)
	{
		ni[i]=0;
		t=1;
		while(t%i!=0)
		{
			ni[i]++;
			t+=MOD;
		}
		ni[i]=(1+ni[i]*MOD)/i;
	}
	k[0][1]=1;
	for(i=1;i<=1000;i++)
	{
		k[i][1]=(k[i-1][1]*ni[i])%MOD;
		k[i][2]=(k[i][1]*k[i][1])%MOD;
	}
	for(i=1;i<=1000;i++)
		for(j=3;j<=1000;j++)
			k[i][j]=(k[i][j-1]*k[i][1])%MOD;
	fact[0]=1;
	for(i=1;i<=1000000;i++)
		fact[i]=(fact[i-1]*i)%MOD;
	while(scanf("%lld%lld%lld",&x,&y,&z)!=EOF)
	{
		a=z;
		b=x*y-a-1;
		ans=x;
		if(y-1>b)
		{
			printf("0\n");
			continue;
		}
		for(i=b;i>b-y+1;i--)
			ans=(ans*i)%MOD;
		for(i=1;i<=y-1;i++)
			ans=(ans*ni[i])%MOD;
		ans=(ans*k[y][x-1])%MOD;
		ans=(ans*fact[(x-1)*y])%MOD;
		printf("%lld\n",ans);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值