• bzoj3198[Sdoi2013]spring


    Sol:

    对月份进行枚举,也就是说看在这些月份中,N行中,有哪些行是两两相等的
    至于判相等,则使用Hash表进行存储与查找.

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #define ll long long
    #define N 100005
    #define mod 2150527
    using namespace std;
    int a[N][10],bin[10],hd[mod+10],vis[mod+10],c[10][10],sum[N],nxt[N],n,m;
    ll val[N];
    void pre()
    {
        for(int i=0;i<=6;i++)
            c[i][0]=c[i][i]=1;
        for(int i=1;i<=6;i++)
        for(int j=1;j<i;j++)
        c[i][j]=c[i-1][j-1]+c[i-1][j];
    }
    ll calc(int st)
    {
        ll ans=0;int tot=0;
        for(int i=1;i<=n;i++)//枚举行 
        {
            ll tmp=0;int j,k;
            for(j=1;j<=6;j++)//对于每行的六个数字
               if(st&bin[j-1])//看哪些月份在我们枚举的范围内 
                   tmp=tmp*1000003+a[i][j];
            //将其hash出来 
            j=tmp%mod;
            j<0?j+=mod:1;
            if(vis[j]!=st)
            {
                vis[j]=st;
                hd[j]=0;
            }
            for(k=hd[j];k;k=nxt[k])
            {
                if(val[k]==tmp)
                {
                    ans+=sum[k];
                    sum[k]++;
                    break;
                }
            }
            if(!k)
            {
                val[++tot]=tmp;
                sum[tot]=1;
                nxt[tot]=hd[j];
                hd[j]=tot;
            }
        }
        return ans;
        //统计对于N行,在我们枚举的月份内,有多少对是相互相等的 
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
             for(int j=1;j<=6;j++)
                  scanf("%d",&a[i][j]);
        bin[0]=1;
        pre();
        for(int i=1;i<=8;i++)
        bin[i]=bin[i-1]<<1;
        ll ans=0;
        for(int i=0;i<64;i++)
        //枚举月份,统计对于N行来说,它们在这i个月有多少个是互相相等的
        //由于对其它月份没有统计,所以是至少这i个月是互相相等的 
        {
            int cnt=0;
            for(int j=0;j<6;j++) //看有效月份有几个 
                if(i&bin[j])
                    cnt++;
            if(cnt<m)
                continue;
            ll t=calc(i)*c[cnt][m];
            if((cnt-m)%2)
                ans-=t;
            else 
                ans+=t;
        }
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    成都磨子桥技工学校 / 数据结构 Challenge 4
    圆桌问题(网络流24题)
    试题库问题(网络流24题)
    [AHOI2005]航线规划
    [AMPPZ2014]The Prices
    方格取数(网络流24题)
    太空飞行计划问题(网络流24题)
    Linux 学习3
    Linux 学习2
    Linux 学习1
  • 原文地址:https://www.cnblogs.com/cutemush/p/12019506.html
Copyright © 2020-2023  润新知