题目:http://acm.hdu.edu.cn/showproblem.php?pid=5330
题意:给出n个长度为m,并且只有012组成的串,两个串的距离为每一位相差的绝对值相加,问距离为0-2m的对数分别有几对
参考:http://blog.csdn.net/glqac/article/details/48971143
最后计算答案的时候,距离为0的话只能跟相同串的互相选择,不为零就是直接相乘
最后所有对数都算了两遍,所以要除2
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<stack> #include<map> #include<set> using namespace std; const int N=2e5+5; int cnt[N],dp[2][N][25]; int f[20]; char s[20]; long long ans[25]; int now=0,pre=1; int main() { f[0]=1; for(int i=1;i<=11;i++) f[i]=f[i-1]*3; int T; scanf("%d",&T); while(T--) { int n,m; scanf("%d%d",&n,&m); memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;i++) { scanf("%s",s); int sum=0; for(int j=0;j<m;j++) sum=sum*3+s[j]-‘0‘; cnt[sum]++; } memset(dp[now],0,sizeof(dp[now])); for(int i=0;i<f[m];i++) dp[now][i][0]=cnt[i]; for(int i=0;i<m;i++) { swap(now,pre); memset(dp[now],0,sizeof(dp[now])); for(int j=0;j<f[m];j++) for(int k=0;k<=2*m;k++) if (dp[pre][j][k]) { int tem=j/f[i]%3; for(int l=0;l<=2;l++) { int t=j-(tem-l)*f[i]; dp[now][t][k+abs(tem-l)]+=dp[pre][j][k]; } } } memset(ans,0,sizeof(ans)); for(int i=0;i<f[m];i++) { if (!cnt[i]) continue; ans[0]+=1LL*cnt[i]*(cnt[i]-1);//dp[now][i][0]==cnt[i] for(int j=1;j<=2*m;j++) ans[j]+=1LL*cnt[i]*dp[now][i][j]; } for(int i=0;i<=2*m;i++) printf("%lld\n",ans[i]/2LL); } return 0; }
时间: 2024-12-11 17:24:51