牛牛的棋盘
做法:打完AT 再来肝牛客,30分钟内居然没AK ,C题 正着算太复杂了,一个角。两个角。三个角。交一发通过 9%
正确的方法是,先计算总的C(n*m,k) 然后减去不合法的。不合法的无非就是 第一行 没有 或者 最后一行没有 或者 第一列没有,最后一列没有。四种情况还会有组合的情况。
于是考虑容斥 用4位 第一位和第二位为1 代表 第一行 和最后一行没有 棋子。第三位 第四位代表第一列和最后一列没有棋子。4位二进制 总共16种情况而已
那么容斥 奇加偶减原理 搞一搞就好了。
class Solution {
public:
/**
*
* @param n int整型
* @param m int整型
* @param k int整型
* @return int整型
*/
long long C[1000][1000];
long long getC(int n, int m)
{
if(n < m || n < 0 || m < 0) return 0;
return C[n][m];
}
int solve(int n, int m, int k) {
// write code here
long long mod=1e9+7;
for(int i = 0; i < 1000; ++i) C[i][0] = C[i][i] = 1;
for(int i = 2; i < 1000; ++i){
for(int j = 1; j <= i; ++j){
C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;
}
}
int res = getC(n*m, k);
//cout<<res<<endl;
for(int i = 1; i < 16; ++i){
int x = n, y = m;
int num = 0;
if(i&1) num++, x--;
if(i&2) num++, x--;
if(i&4) num++, y--;
if(i&8) num++, y--;
//2printf("x:%d y:%d k:%d\n", x, y, k);
if(num&1) res = (res - getC(x * y, k) + mod) % mod;
else res = (res + getC(x * y, k)) % mod;
}
return res;
}
};