zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    斐波那契数列 详解
    ASP.NET 系列:RBAC权限设计
    架构系列:ASP.NET 项目结构搭建
    EntityFramework系列:Repository模式与单元测试
    PHP 系列:PHP Web 开发基础
    Java Web系列:Spring Boot 基础
    ddddddd
    ddd
    asdfsf
    sdfsdfsdf
  • 原文地址:https://www.cnblogs.com/cutemush/p/12019506.html
Copyright © 2011-2022 走看看