[Sdoi2013]spring

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3198

题意不赘述了,很好懂吧。。这题应该算是送分题了。解法大概就是容斥+哈希。

具体来说,就是2^6枚举至少对应位相同的方案,假如枚举了101100,表示至少第1,2,4相同的方案,设其中1的个数为m。那么对答案的贡献就是(-1)^(k-m)*方案数*C(k,m),这其实就是容斥。

现在的问题是确定了对应位,然后算方案数,怎么算?。其实就是枚举1到n,把对应为hash起来,扔进hash表里面,每次加上之前这个组合以前出现的次数,然后在计数器++就好了。是不是很简单?

/**************************************************************
    Problem: 3198
    User: hta
    Language: C++
    Result: Accepted
    Time:10280 ms
    Memory:8036 kb
****************************************************************/
 
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <string>
using namespace std;
typedef long long LL;
const int maxh=231733,maxn=100003,seed=13313;
int a[maxn][6],n,K,C[7][7],num[6];
int Link[maxh],pre[maxn],t[maxn][6],v[maxn],tot=0,top=0,stk[maxn];
inline int get()
{
    int f=0,v=0;char ch;
    while(!isdigit(ch=getchar()))if(ch=='-')break;
    if(ch=='-')f=1;else v=ch-48;
    while(isdigit(ch=getchar()))v=v*10+ch-48;
    if(f==1)return -v;else return v;
}
 
int insert(int x,int n)
{
    for(int i=Link[x];i;i=pre[i])
    {
        bool f=1;
        for(int j=0;j<n;j++)
            if(t[i][j]!=num[j])f=0;
        if(f)return ++v[i];
    }
    if(Link[x]==0)stk[++top]=x;
    pre[++tot]=Link[x]; Link[x]=tot; v[tot]=0;
    for(int i=0;i<n;i++)t[tot][i]=num[i];
    return 0;
}
 
void clear()
{
    while(top)Link[stk[top--]]=0;
    tot=0;
}
 
int main()
{
    n=get();K=get();
    for(int i=1;i<=n;i++)
        for(int j=0;j<6;j++)a[i][j]=get();
    C[0][0]=1;
    for(int i=1;i<=6;i++)
    {
        C[i][0]=1;
        for(int j=1;j<=i;j++)C[i][j]=C[i-1][j]+C[i-1][j-1];
    }
    LL ans=0;
    for(int i=0;i<64;i++)
    {
        int tp=0;
        for(int j=i;j;j-=j&-j)tp++;
        if(tp<K)continue;
        LL res=0;
        for(int j=1;j<=n;j++)
        {
            int hash=0;
            for(int k=0,t=0;k<6;k++)
                if(i&(1<<k))num[t++]=a[j][k],hash=(LL(hash)*seed+a[j][k])%maxh;
            res+=insert(hash,tp);
        }
        clear();
        if((tp-K)&1)ans-=res*C[tp][K];else ans+=res*C[tp][K];
    }
    cout<<ans<<endl;
    return 0;
}


你可能感兴趣的:([Sdoi2013]spring)