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

      

  • 相关阅读:
    Uva11235
    Uva11300/BZOJ1045/BZOJ1465/BZOJ3292
    树形背包模板
    Miller-Rabin素性测试
    BZOJ1500 : [NOI2005]维修数列-fhq_Treap
    COGS2421 [HZOI 2016]简单的Treap
    用 fhq_Treap 实现可持久化平衡树
    hdu 1010(DFS) 骨头的诱惑
    hdu 1026(BFS+输出路径) 我要和怪兽决斗
    hdu 1072(BFS) 有炸弹
  • 原文地址:https://www.cnblogs.com/joyouth/p/5392884.html
Copyright © 2011-2022 走看看