牛客编程巅峰赛S1第2场 - 青铜&白银(C 组合数学 容斥)

牛牛的棋盘

做法:打完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;


}
};

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/107312318