HDU5823color II

怎麼現在FWT啥的都爛大街了呀
將集合S分爲兩個沒有連邊的集合A B

F[i][S]表示集合S能否用i種顏色染色
則有
F[i][S]=[ASF[i1][A]F[1][B]>0]
多美的一個卷積形式啊

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
using namespace std;
char c;
inline void read(int&a)
{a=0;do c=getchar();while(c<'0'||c>'9');while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}


int UFMT(int *a,int n)
{
    for(int i=1;i<=n;i++)
        for(int j=0;j<(1<<n);j++)
            if(j&(1<<i-1))
            {
                int t=1<<i-1;
                    a[j]-=a[j^t];
            }

}

int FMT(int *a,int n)
{

    for(int i=1;i<=n;i++)
        for(int j=0;j<(1<<n);j++)
            if(j&(1<<i-1))
            {
                int t=1<<i-1;
                    a[j]+=a[j^t];
            }
}
unsigned int Ans;
unsigned int Pow(unsigned int A,unsigned int X)
{
    unsigned int res=1;
    for(X;X;X>>=1,A*=A)
        if(X&1)res*=A;
    return res;
}
bool map[21][21];
int A[262144],B[2][262144];
int n,T;
char S[101];
int Op[10001];
bool OK[262144];
int Rev[262144];
int main()
{
    read(T);
    while(T--)
    {
        read(n);

        for(int i=1;i<=n;i++)
        {
            Op[i]=0;
            scanf("%s",S);
            for(int j=1;j<=n;j++,Op[i]<<=1)
                {
                    c=S[n-j];
                    Op[i]|=(c=='1'?1:0);
                }
            Op[i]/=2;
        }
        A[0]=1;
        for(int i=1;i<=n;i++)
            for(int j=0;j<(1<<i-1);j++)
                A[j|(1<<i-1)]=A[j]&((Op[i]&j)?0:1);

        FMT(A,n);
        int last=0,now=1;
        memset(B,0,sizeof(B));
        memset(OK,0,sizeof(OK));
        B[last][0]=1;
        for(int j=1;j<=n;j++,last^=1,now^=1)
        {
            FMT(B[last],n);
            for(int i=0;i<(1<<n);i++)
                B[now][i]=B[last][i]*A[i];
            UFMT(B[now],n);
            for(int i=0;i<(1<<n);i++)
                B[now][i]=!!B[now][i];
            for(int i=1;i<(1<<n);i++)
                if(B[now][i]&&!OK[i])
                    OK[i]=true,Ans+=j*Pow(233,i);
        }
        cout<<Ans<<endl;
        Ans=0;
    }


    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章