Problem
loj
貓錕出的神仙題……流下了不學無術的淚水
Solution
這題是個假的最優化,其實是個計數題
要求權值爲 的生成樹個數,不妨考慮操作符全部爲異或的情況。計數的話還得用Matrix Tree定理,此時矩陣的元素變成了一個桶,且它們的乘法也應該是異或卷積,然而我們並不會定義異或卷積意義下的逆元。
如果我們把桶FWT了,那麼FWT後的數組每一位就都是獨立的了,這樣就可以把每一位單獨列成一個矩陣,用Matrix Tree定理即可求出答案數組相應位置的答案。最後把答案數組IFWT一遍即可得到答案數組。
而對於其他的操作符,就在相應的二進制位上採用相應的FWT方式即可。
時間複雜度 。
算了下感覺跑不過,下了個數據發現跑了13s,於是在求行列式的時候加了個如果對角線上有0就直接返回0之後就只需要跑1.4s了。。感覺有點迷
Code
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn=5010,mod=998244353,inv2=499122177;
template <typename Tp> inline int getmin(Tp &x,Tp y){return y<x?x=y,1:0;}
template <typename Tp> inline int getmax(Tp &x,Tp y){return y>x?x=y,1:0;}
template <typename Tp> inline void read(Tp &x)
{
x=0;int f=0;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
if(f) x=-x;
}
int n,m,l,N,a[80][80],G[80][80][maxn],ans[maxn];
char op[20],s[maxn];
int pls(int x,int y){return x+y>=mod?x+y-mod:x+y;}
int dec(int x,int y){return x<y?x-y+mod:x-y;}
int power(int x,int y)
{
int res=1;
for(;y;y>>=1,x=(ll)x*x%mod)
if(y&1)
res=(ll)res*x%mod;
return res;
}
void FWT(int *a,int f)
{
for(int i=1;i<N;i<<=1)
for(int j=0;j<N;j+=(i<<1))
for(int k=0;k<i;++k)
{
if(s[i]=='&')
a[j+k]=f?pls(a[j+k],a[j+k+i]):dec(a[j+k],a[j+k+i]);
if(s[i]=='|')
a[j+k+i]=f?pls(a[j+k],a[j+k+i]):dec(a[j+k+i],a[j+k]);
if(s[i]=='^')
{
int x=a[j+k],y=a[j+k+i];
a[j+k]=pls(x,y);a[j+k+i]=dec(x,y);
if(!f)a[j+k]=(ll)a[j+k]*inv2%mod,a[j+k+i]=(ll)a[j+k+i]*inv2%mod;
}
}
}
void input()
{
int x,y,v;
read(n);read(m);scanf("%s",op+1);
l=strlen(op+1);N=1<<l;
for(int i=1;i<=l;i++) s[1<<(i-1)]=op[i];
for(int i=1;i<=m;i++)
{
read(x);read(y);read(v);
G[x][y][v]=dec(G[x][y][v],1);
G[y][x][v]=dec(G[y][x][v],1);
++G[x][x][v];++G[y][y][v];
}
}
int gauss()
{
int det=1,inv;
for(int i=1,k;i<n;i++)
{
if(!a[i][i])
{
k=0;
for(int j=i;j<n;j++) if(a[j][i]){k=j;break;}
if(k==0) return 0;
swap(a[i],a[k]);
}
det=(ll)det*a[i][i]%mod;inv=power(a[i][i],mod-2);
for(int j=i+1;j<n;j++) a[i][j]=(ll)a[i][j]*inv%mod;
for(int j=i+1;j<n;j++)
for(int r=i+1;r<n;r++)
a[j][r]=dec(a[j][r],(ll)a[j][i]*a[i][r]%mod);
}
return det;
}
int main()
{
input();
for(int i=1;i<n;i++)
for(int j=1;j<=i;j++)
{
FWT(G[i][j],1);
if(j<i) memmove(G[j][i],G[i][j],sizeof(G[i][j]));
}
for(int s=0;s<N;++s)
{
for(int i=1;i<n;i++)
for(int j=1;j<n;j++)
a[i][j]=G[i][j][s];
ans[s]=gauss();
}
FWT(ans,0);
for(int i=N-1;~i;i--) if(ans[i]) {printf("%d\n",i);return 0;}
puts("-1");
return 0;
}