题意:
给出n (n<=50000) 个长度为4的字符串,问有且仅有d(1<=d<=4)处不相同的字符串有几对。
SOL:
一直对着4发呆,这么小的字符串背后有什么玄学呢= =...既不能放在TRIE上搞似乎也套不了什么东西,一直很好奇这种题目能不能用某个神奇的字符串HASH水过...然后颓了一会儿突然想到,如果我们只是判断字符串相等不相等的话,因为每个位置只有36种状态,直接开个36^4的数组加加减减然后搞个组合数就好了.
那不是可以迁移过来吗?!!!!!!!
在那个问题之上,我们要解决的是两个字符串之间不同的个数---->考虑到我们可以把一个字符串拆成其按顺序的各个排列组合,然后就变成了上面的那个判定性的问题.分开来好判断,怎么把它合起来呢?容斥啊傻吊...虽然这是在OI上打的第一个容斥不过还是非常..显然?...
CODE:
/*========================================================================== # Last modified: 2016-02-27 09:13 # Filename: t2.cpp # Description: ==========================================================================*/ #define me AcrossTheSky #include <cstdio> #include <cmath> #include <ctime> #include <string> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <set> #include <map> #include <stack> #include <queue> #include <vector> #define lowbit(x) (x)&(-x) #define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++) #define FORP(i,a,b) for(int i=(a);i<=(b);i++) #define FORM(i,a,b) for(int i=(a);i>=(b);i--) #define ls(a,b) (((a)+(b)) << 1) #define rs(a,b) (((a)+(b)) >> 1) #define getlc(a) ch[(a)][0] #define getrc(a) ch[(a)][1] #define maxn 40 #define maxm 100000 #define pi 3.1415926535898 #define _e 2.718281828459 #define INF 1070000000 using namespace std; typedef long long ll; typedef unsigned long long ull; template<class T> inline void read(T& num) { bool start=false,neg=false; char c; num=0; while((c=getchar())!=EOF) { if(c=='-') start=neg=true; else if(c>='0' && c<='9') { start=true; num=num*10+c-'0'; } else if(start) break; } if(neg) num=-num; } /*==================split line==================*/ int a[5]; ll sum[maxn][maxn][maxn][maxn],ans[10]; bool check(char c){ if (c>='0' && c<='9') return false; return true;} void init(char *s){ FORP(i,0,15){ FORP(j,0,3) if (i & 1<<j) a[j]=check(s[j])?s[j]-'a'+10:s[j]-'0'; else a[j]=36; //FORP(i,0,3) printf("%d ",a[i]); printf(" "); sum[a[0]][a[1]][a[2]][a[3]]++; } //printf(" "); } int judge(int x){if (x<36) return 1; else return 0;} void solve(){ FORP(k,0,36) FORP(l,0,36) FORP(m,0,36) FORP(n,0,36){ ll f=judge(k)+judge(l)+judge(m)+judge(n),p=sum[k][l][m][n]; ans[f]+=(p*(p-1)/2); } } int main(){ ll n,d; read(n); read(d); FORP(i,1,n){ char s[10]; scanf("%s",s); init(s); } solve(); //FORP(i,0,4) printf("%d ",ans[i]); //cout << endl; //FOR(d,1,4){ if (d==1) printf("%lld ",ans[3]-4*ans[4]); if (d==2) printf("%lld ",ans[2]-3*ans[3]+6*ans[4]); if (d==3) printf("%lld ",ans[1]-2*ans[2]+3*ans[3]-4*ans[4]); if (d==4) printf("%lld ",ans[0]-ans[1]+ans[2]-ans[3]+ans[4]); //} }