聯考20200721 T1 s1mple
阿新 • • 發佈:2020-07-22
分析:
大佬部落格膜了膜了
撲通撲通跪下來
#include<cstdio> #include<cmath> #include<cstring> #include<iostream> #include<algorithm> #include<queue> #include<set> #include<map> #include<vector> #include<string> #define maxn 18 #define INF 0x3f3f3f3f #define MOD 998244353 using namespace std; inline int getint() { int num=0,flag=1;char c; while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1; while(c>='0'&&c<='9')num=num*10+c-48,c=getchar(); return num*flag; } int n,Q; long long f[maxn][1<<maxn],g[1<<maxn][maxn],sz[1<<maxn]; long long a[1<<maxn],ans[1<<maxn]; char s[maxn]; int c[maxn][maxn]; vector<int>tmp; inline int solve(int x) { int t=0;tmp.clear(); for(int i=n-2;~i;--i){t++;if(((x>>i)&1)==0)tmp.push_back(t),t=0;} tmp.push_back(t+1); sort(tmp.begin(),tmp.end()); int num=0; for(int i=0;i<tmp.size();i++)num=(num<<tmp[i])+((1<<tmp[i]-1)-1); return num; } inline void FWT(long long *a,int n) { for(int i=1;i<n;i<<=1)for(int j=0;j<n;j+=i<<1) for(int k=j;k<j+i;k++)a[k+i]+=a[k]; } inline void IFWT(long long *a,int n) { for(int i=1;i<n;i<<=1)for(int j=0;j<n;j+=i<<1) for(int k=j;k<j+i;k++)a[k+i]-=a[k]; } int main() { n=getint(); for(int i=0;i<n;i++) { scanf("%s",s); for(int j=0;j<n;j++)c[i][j]=s[j]-48; } f[0][0]=1; for(int i=0;i<(1<<n);i++) { sz[i]=sz[i>>1]+(i&1); for(int j=0;j<n;j++)if(i&(1<<j)) { int t=i^(1<<j); if(!t)g[i][j]=1; for(int k=0;k<n;k++)if(c[j][k])g[i][j]+=g[t][k]; f[sz[i]][i]+=g[i][j]; } } for(int i=0;i<=n;i++)FWT(f[i],1<<n); memset(ans,-1,sizeof ans); for(int i=0;i<(1<<(n-1));i++) { int t=solve(i); if(~ans[t]){ans[i]=ans[t];continue;} for(int j=0;j<(1<<n);j++)a[j]=1; for(int j=0;j<tmp.size();j++) for(int k=0;k<(1<<n);k++)a[k]*=f[tmp[j]][k]; IFWT(a,1<<n); ans[i]=ans[t]=a[(1<<n)-1]; } for(int i=1;i<(1<<(n-1));i<<=1)for(int j=0;j<(1<<(n-1));j+=i<<1) for(int k=j;k<j+i;k++)ans[k]-=ans[k+i]; Q=getint(); while(Q--) { scanf("%s",s);int x=0; for(int i=0;i<n-1;i++)x=(x<<1)|(s[i]-48); printf("%lld\n",ans[x]); } }