bzoj3198[Sdoi2013]spring

Sol:

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

猜你喜欢

转载自www.cnblogs.com/cutemush/p/12019506.html