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;
}