Rivendell’s pearls(pearls)(hash+容斥原理)

    xiaoxiao2025-05-16  9

    Rivendell’s pearls(pearls) 【问题描述】 Rivendell 是一个心灵手巧的男孩子,他在闲暇的时候喜欢做一些小饰品。 有一天 Rivendell用漂亮的珍珠做成了 n串手链,并且每串手链都由 4个珍 珠构成,并且每粒珍珠都有一种颜色,颜色用小写字母和数字表示。现在他突然 想知道这n 串手链中有多少对有且仅有k 粒珍珠是不同颜色的。 【输入格式】 第一行两个整数 n和 k。 接下来 n个长度为 4的字符串。 【输出格式】 一个整数表示答案。 【样例输入】 4 2 0000 a010 0202 a0e2 【样例输出】 3 【数据规模及约定】 对于 15%的数据,n<=2000 对于 60%的数据,k<=2。其中50%的数据,k=1 对于 75%的数据,字符串中只有字母a 到f 对于 100%的数据,n<=50000,k<=4

    #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define ul unsigned long long #define LL long long #define p 2000001001 #define N 50003 using namespace std; int n,m,k,len; char s[10]; int ch[N][10],ans[N],vis[N]; LL tot,base[10][10]; ul mi[N],hash[N]; struct data { int x; ul num,num1; }a[N]; int cmp(data x,data y) { return x.num<y.num||x.num==y.num&&x.num1<y.num1; } void solve1() { for (int i=1;i<=n;i++) { a[i].num=hash[i],a[i].num1=0; a[i].x=i; for (int j=1;j<=k;j++) a[i].num-=ch[i][ans[j]]*mi[ans[j]-1], a[i].num1-=ch[i][ans[j]]*mi[ans[j]-1]; } sort(a+1,a+n+1,cmp); LL sum=1,sum1=1; for (int i=2;i<=n;i++) if (a[i].num==a[i-1].num) { if (a[i].num1==a[i-1].num1) sum1++; else tot-=(sum1-1)*sum1/2,sum1=1; sum++; if (i==n) tot-=sum1*(sum1-1)/2,tot+=(sum-1)*sum/2;//cout<<tot<<endl; } else { tot-=(sum1-1)*sum1/2; tot+=(sum-1)*sum/2; sum=1,sum1=1; } } void dfs(int x,int now) { if (x==k+1) { if (k==1) solve1(); return; } for (int i=now;i<=4;i++) { ans[x]=i; dfs(x+1,i+1); } } void solve() { for (int i=1;i<=n;i++) { a[i].num=hash[i],a[i].num1=0; a[i].x=i; for (int j=1;j<=len;j++) a[i].num-=ch[i][ans[j]]*mi[ans[j]-1]; } sort(a+1,a+n+1,cmp); LL sum=1,ans1=base[k][len]; for (int i=2;i<=n;i++) if (a[i].num==a[i-1].num) { sum++; if (i==n) tot+=ans1*(sum-1)*sum/2; } else { tot+=ans1*(sum-1)*sum/2; sum=1; } } void dfs1(int x,int now) { if (x==len+1) { solve(); return; } for (int i=now;i<=4;i++) { ans[x]=i; dfs1(x+1,i+1); } } LL calc() { sort(hash+1,hash+n+1); LL sum=1,ans1=0; for (int i=2;i<=n;i++) if (hash[i]==hash[i-1]) { sum++; if (i==n) ans1+=sum*(sum-1)/2; } else { ans1+=sum*(sum-1)/2; sum=1; } return ans1; } int main() { freopen("pearls.in","r",stdin); freopen("pearls.out","w",stdout); scanf("%d%d",&n,&k); for (int i=1;i<=n;i++) { scanf("%s",s+1); for (int j=1;j<=4;j++) ch[i][j]=s[j]; } mi[0]=1; for (int i=1;i<=4;i++) mi[i]=mi[i-1]*p; for (int i=1;i<=n;i++) { for (int j=1;j<=4;j++) hash[i]+=mi[j-1]*ch[i][j]; } if (k==0) { sort(hash+1,hash+n+1); LL sum=1,ans1=0; for (int i=2;i<=n;i++) if (hash[i]==hash[i-1]) { sum++; if (i==n) ans1+=sum*(sum-1)/2; } else { ans1+=sum*(sum-1)/2; sum=1; } printf("%I64d\n",ans1); return 0; } if (k==1) { dfs(1,1); printf("%I64d\n",tot); return 0; } base[2][0]=6; base[2][1]=-3; base[2][2]=1; base[3][0]=-4; base[3][1]=3; base[3][2]=-2; base[3][3]=1; base[4][0]=1; base[4][1]=-1; base[4][2]=1; base[4][3]=-1; base[4][4]=1; for (int i=1;i<=k;i++) { len=i; dfs1(1,1); } printf("%I64d\n",tot+calc()*base[k][0]); }

    转载请注明原文地址: https://ju.6miu.com/read-1298953.html
    最新回复(0)