zoukankan      html  css  js  c++  java
  • 模拟题-code

    code

    题意

    给定一个M*N 的矩阵,矩阵中每个数都是一个 K 位 2 进制数,把矩阵每一行的数都或起来,得到 N 个数,把每一列的数都或起来,得到 M 个数,让得到的n+m个数都等于2k-1

    样例

    in

    多组测试数据,在输入的第一行会给出测试数据组数 T 。
    每组测试数据一共一行,为三个整数N,M,K。
    4
    1 1 31
    1 10 2
    2 2 1
    2 3 2

    out

    输出每组数据一行,即答案。
    1
    1
    7
    625

    闲扯

    一共三个半小时的考试,在这题上花了俩还多

    而且 竟然爆零了

    而且 听人家AC的讲题没听懂

    而且 听听懂的人讲题还没懂

    我这种蒟蒻是不是没救了

    最后照着AC代码模拟。。。

    然后

    如果发现有不合理的地方,欢迎指出

    如果发现有不合理的地方,欢迎指出

    如果发现有不合理的地方,欢迎指出

    思路

    因为二进制的每一位是互相独立的,只需要算出m*n的矩阵或起来是1的方案数

    最后算k次方

    容斥原理

    总情况2^(n*m)

    总情况中包含“一行零列”这种不合法情况
    需要减去这种情况
    同时总情况中也包含“零行一列”这种不合法情况
    需要减去这种情况
    但是减去这两项的话
    “一行一列”这种情况就被减了两次
    需要再加一次

    同理
    由于“i-1行j列”和“i行j-1列”的重复计算
    使得“i行j列”的情况多减了,需要与上述运算的符号相反
    即:i,j组合的符号是根据上面的计算推出来的

    res:仅考虑i行j列中没有1的情况总数
    C(n,i)*C(m,j)是把行列选出来
    Pow(2^(n*m-i*m-j*n+i*j))是说:剩下的格子随意,当前仅考虑选出的i行j列中没有1

    代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    #define N 100005
    #define LL long long
    #define mod 1000000007
    long long a[55];
    void pre(){
        a[0]=1;
        for(int i=1;i<=50;i++){
            a[i]=a[i-1]*i%mod;
        }
    }
    inline void putout(long long x){
        char c[15];
        int k=0;
        if(x<0) putchar('-'),x=-x;
        do {
            c[++k]=x%10+48;
            x/=10;
        } while(x);
        while(k) putchar(c[k--]);
    }
    inline long long fastpow(long long now,int k){
        long long mul=now;
        long long ret=1LL;
        while(k){
            if(k%2){
                ret=ret*mul%mod;
            }
            mul=mul*mul%mod;
            k>>=1;
        }
        return ret;
    }
    long long C(int n,int m){
        LL ret=1LL*(a[n]*fastpow(a[m],mod-2)%mod)*
                    fastpow(a[n-m],mod-2)%mod;
        return ret;
    }
    int main(){
        freopen("code.in","r",stdin);
        freopen("code.out","w",stdout);
        int T;
        pre();
        scanf("%d",&T);
        while(T--){
            int n,m,k;
            scanf("%d%d%d",&n,&m,&k);
            long long ans=0;
            for(int i=0;i<=n;i++){
                for(int j=0;j<=m;j++){
                    int plus=((i+j)%2) ? -1:1;
                    long long fast=fastpow(2,n*m-i*m-j*n+i*j);
                    long long res=(1LL*C(n,i)*C(m,j)%mod)*fast%mod;
                    ans=(ans+res*plus)%mod;
                }
            }
            ans=(ans+mod)%mod;
            ans=fastpow(ans,k);
            printf("%I64d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    C++虚函数表理解
    【转】c++虚函数实现原理
    【转】运输层TCP协议详细介绍
    【转】计算机中浮点数的表示
    ARP跨网段广播
    【转】arm和x86的区别
    面向对象六大原则
    安卓 热修复的原理
    Zygote和System进程的启动过程
    Android内存泄漏
  • 原文地址:https://www.cnblogs.com/aptx--4869/p/9851863.html
Copyright © 2011-2022 走看看