Cheerleaders UVa11806 容斥+基本计数原理 思维题 好题 套路题

https://cn.vjudge.net/contest/236754#problem/C

基本大意就是 一个 m*n的棋盘吧 k个棋子 全放完有什么方法 附加条件:第一行第一列最后一行最后一列都要有棋子


如果没有附加条件 很好做 就是C mn k 但是加了条件 就不一样了

我开始是朴素的想这道题 最后发现自己太幼稚了 想什么呢 o(╥﹏╥)o

之后从条件入手 这么多条件 最后要求交集

(然后我唛头规整在纸上下下来思考过程结果发现手机相机坏了!!!┭┮﹏┭┮那我打字吧)


条件重述:要求C1交C2交C3交C4(其中C1:第一行有棋子    C2:最后一行有棋子    C3:第一列有棋子    C4:最后一列有棋子)

这样的话求交集遵循“奇加偶减”原则。但是问题是 你求出C1太难求啦 但是你可以求 非C1

so...

我们可以通过 非C1非C2非C3非C4通过“奇减偶加”原则得到 C1交C2交C3交C4

(代码里的S是二进制位表示是否满足这四种条件 这个套路百用不厌啊d(´ω`*))

上AC代码

#include <iostream>
#include<cstdio>
#include<cstring>

using namespace std;

const int MOD = 1000007;
const int MAXK = 500;
int C[MAXK][MAXK];

int main(){
	memset(C,0,sizeof(C));
	for(int i = 0;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 T;
	scanf("%d",&T);
	for(int Case = 1;Case <= T;Case++){
		int n,m,k,sum = 0;
		scanf("%d%d%d",&n,&m,&k);
		for(int S = 0;S < 16;S++){
			int b = 0,r = n,c = m;
			if(S&1){r--;b++;}
			if(S&2){r--;b++;}
			if(S&4){c--;b++;}
			if(S&8){c--;b++;}
			if(b&1) sum = (sum + MOD - C[r*c][k]) % MOD;
			else sum = (sum + C[r*c][k]) % MOD;
		} 
		printf("Case %d: %d\n",Case,sum);
	} 
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值