串 & 容斥原理

题意:

  给出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("\n");
        sum[a[0]][a[1]][a[2]][a[3]]++;
    }
    //printf("\n");
}
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\n",ans[3]-4*ans[4]);
    if (d==2) printf("%lld\n",ans[2]-3*ans[3]+6*ans[4]);
    if (d==3) printf("%lld\n",ans[1]-2*ans[2]+3*ans[3]-4*ans[4]);
    if (d==4) printf("%lld\n",ans[0]-ans[1]+ans[2]-ans[3]+ans[4]);
    //}
}

 

posted @ 2016-02-27 14:44  YCuangWhen  阅读(239)  评论(0编辑  收藏  举报