怎麼現在FWT啥的都爛大街了呀
將集合S分爲兩個沒有連邊的集合A B
F[i][S]表示集合S能否用i種顏色染色
則有
多美的一個卷積形式啊
#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;
}