UVA 11806 - Cheerleaders

我的思路一点都没错,就是求组合的时候出了点错T T

直接容斥原理就好了。

设A(去掉最后一行)B(去掉最上面一行)C(去掉最右边一行)D(去掉最左边一行)

Ans= A∪B∪C∪D

-A-B-C-D

+ A∩B + A∩C + A∩D + B∩C + B∩D + C∩D

- A∩B∩C-  A∩B∩D- A∩C∩D - B∩C∩D

+  A∩B∩C∩D

我把它分行了,这样比较好看^ ^

整理可得:(设组合数为c(n,k) )

ans=c(m * n,k)

         -2* c(m * (n-1), k )  -  2 * c( n * (m-1),k)

         +c(n * (m-2),k)    +c( (n-2) * m,k)  + 4 * c((n-1) * (m-1),k)

         -2* c((m-2) * (n-1),k) -2 * c((m-1) * (n-2),k)

         +c( (m-2) * (n-2),k)

 

嗯,接下来只要求组合数就可以啦~

来看看一段求组合数的代码:

运用了c(n,k)=(n-k+1) / k *c(n,k-1)

 

int c(long long  n,long long k)  //思路是没有错的,但是过程不对,mod运算不对/封闭。
{
	if(n==0||n<k) return 0;
	if(k>n/2) k=n-k;
	long long ans=1;
	for(long long i=1;i<=k;i++)
		ans=ans*(n-i+1)/i % mod;
	return ans % mod;
}

思路是没有错的,但是过程不对,mod运算不对/封闭。

想想Mod运算:

(a+b)% c=(a % c + b % c) % c

(a-b)% c=( a % c –b % c +c) % c        //你无法保证a % c  >  b %c

(ab)% c=( a %c ) * ( b%c ) % c

但是没有除法!!!

那么,要如何求呢?可以运用

C(n,k)=C(n-1,k-1)+C(n-1,k)


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define c(n,k) (C[n][k])
const int mod=1000007;
const int MAXK = 500;
int C[MAXK+10][MAXK+10];
int main()
{
	memset(C,0,sizeof(C));	
    C[0][0] = 1;			//没有直接WA
	for(int i=1;i<=MAXK;i++)
	{
		C[i][0]=C[i][i]=1;
		for(int j=1;j<i;j++)
			C[i][j]=(C[i-1][j-1]+C[i-1][j]) %mod;
	}
	int repeat;
	scanf("%d",&repeat);
	for(int ri=1;ri<=repeat;ri++)
	{
		int n,m,k,ans;
		scanf("%d%d%d",&m,&n,&k);
		 ans=((((c(m * n,k) % mod
			 -2 * c(m * (n-1), k ) % mod - 2 * c( n * (m-1),k) % mod + 4*mod ) % mod
			 + c(n * (m-2),k) % mod +c( (n-2) * m,k) % mod + 4 * c((n-1) * (m-1),k) % mod ) %mod
			 -2 * c((m-2) * (n-1),k) % mod - 2 * c((m-1) * (n-2),k) % mod +4*mod )%mod
			 + c( (m-2) * (n-2),k) % mod ) %mod ;
		printf("Case %d: %d\n",ri,ans);

	}
}


你可能感兴趣的:(UVA 11806 - Cheerleaders)