zoukankan      html  css  js  c++  java
  • BZOJ 3198 SDOI2013 spring

    为什么SDOI省选一年考两次容斥原理?

    我们很容易发现>=k个相等时很好计算的

    但是我们要求恰好k个,那么我们容斥即可

    至于计算>=k个相等,首先我们枚举相等位置,对每个串对应位置做一遍hash就可以了

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    using namespace std;
     
    typedef long long LL;
    const int maxn=100010;
    const int x=1333331;
    const int mod=100007;
    int n,k,lim;
    int Num[maxn];
    int jc[maxn];
    LL A[6][maxn];
    LL Hash[maxn];
    LL ans;
     
    void read(int &num){
        num=0;char ch=getchar();
        while(ch<'!')ch=getchar();
        while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
    }
    struct HASMMAP{
        int h[mod+10],next[200010],cnt;
        int val[200010];
        LL S[200010];
        void init(){memset(h,0,sizeof(h));cnt=0;}
        void push(LL Hash){
            int key=Hash%mod;
            if(key<0)key+=mod;
            for(int i=h[key];i;i=next[i]){
                if(S[i]==Hash){val[i]++;return;}
            }
            ++cnt;next[cnt]=h[key];h[key]=cnt;
            S[cnt]=Hash;val[cnt]=1;
        }
        int ask(LL Hash){
            int key=Hash%mod;
            if(key<0)key+=mod;
            for(int i=h[key];i;i=next[i]){
                if(S[i]==Hash)return val[i];
            }return 0;
        }
    }H;
    LL Get_ans(int k){
        H.init();
        LL sum=0;
        for(int i=1;i<=n;++i){
            LL now=0;
            for(int j=0;j<6;++j){
                if(k>>j&1)now=now*x+A[j][i];
            }
            sum+=H.ask(now);
            H.push(now);
        }return sum;
    }
    LL C(int n,int m){return jc[n]/jc[m]/jc[n-m];}
    int Get_Num(int k){
        int cnt=0;
        for(int i=0;i<6;++i)if(k>>i&1)cnt++;
        return cnt;
    }
     
    int main(){
        read(n);read(k);
        for(int i=1;i<=n;++i)for(int j=0;j<6;++j)scanf("%lld",&A[j][i]);
        jc[0]=1;
        for(int i=1;i<=6;++i)jc[i]=jc[i-1]*i;
        lim=(1<<6);
        for(int i=0;i<lim;++i){
            Num[i]=Get_Num(i);
            if(Num[i]<k)continue;
            if((Num[i]-k)&1)ans=ans-1LL*C(Num[i],k)*Get_ans(i);
            else ans=ans+1LL*C(Num[i],k)*Get_ans(i);
        }printf("%lld
    ",ans);
        return 0;
    }
    

      

  • 相关阅读:
    使用AnsyncTask异步类从网络上下载图片
    fibonacci分治求法
    JavaScript
    JavaScript
    JavaScript
    JavaScript
    yarn安装vue后,报“文件名、目录名或卷标语法不正确。”
    VIM-Plug安装插件时,频繁更新失败,或报端口443被拒绝等
    Node.js Windows Binary二进制文件安装方法
    Linux常用命令
  • 原文地址:https://www.cnblogs.com/joyouth/p/5392884.html
Copyright © 2011-2022 走看看