P9249

· · 题解

一个暴力。

对于 S\in [0,n),求出旅行的预约值的按位与为 S 的超集的方案数,然后做高维差分就能得到答案。

这样做的好处是,如果我们枚举 y,那么所有所有旅行的起点和终点都只需要满足是 S 的超集即可。

f_{i,x} 为当前走了 i 步,位于 x 的方案数,转移分为两种:

f_{i,x}\times A_{x,y}\to f_{i+1,y}

因为旅行至少走一步,所以我们不妨钦定走一步,枚举新旅行的第二个节点。

同样的理由,初始化也应当钦定走一步。 最后的答案就是 $\sum\limits_{x\&S=x}f_{m,x}$。 把转移写成矩阵 $F$,同时设行向量 $P$ 为 $f$ 的初值,列向量 $Q$ 为求答案的系数数组。 那么恰好经过 $i$ 条边的方案数即为 $PF^{i-1}Q$ ,$i-1$ 是因为初始化先走了一步。 取 $B=\sqrt m$,预处理出 $PF^{k},k\in [0,B)$ 以及 $F^{kB}Q$,因为都是矩阵乘向量,单次复杂度 $O(n^2) $。 总复杂度 $O(n(n^2\sqrt m+n^3\log m+nm))$,能过。 ```cpp #include<bits/stdc++.h> using namespace std; const int mod = 998244353; const int N = 64; const int M = 20005; int n,m; inline int myplus(int a,int b){return (a+b>=mod?a+b-mod:a+b);} struct vec { int mt[N]; vec(){memset(mt,0,sizeof(mt));} int &operator [](int x){return mt[x];} }Ma[150],Mb[150]; int operator *(vec A,vec B) { int res=0; for(int k=0;k<n;k++) res=myplus(res,1ll*A[k]*B[k]%mod); return res; } struct mat { int mt[N][N]; mat(){memset(mt,0,sizeof(mt));} inline int* operator [](int x){return mt[x];} }G; mat operator *(mat A,mat B) { mat C; for(int k=0;k<n;k++) for(int i=0;i<n;i++) for(int j=0;j<n;j++) C[i][j]=myplus(C[i][j],1ll*A[i][k]*B[k][j]%mod); return C; } vec operator *(vec A,mat B) { vec C; for(int i=0;i<n;i++) for(int k=0;k<n;k++) C[i]=myplus(C[i],1ll*A[k]*B[k][i]%mod); return C; } vec operator *(mat A,vec B) { vec C; for(int i=0;i<n;i++) for(int k=0;k<n;k++) C[i]=myplus(C[i],1ll*A[i][k]*B[k]%mod); return C; } mat Pow(mat a,int b) { mat res; for(int i=0;i<n;i++)res[i][i]=1; while(b) { if(b&1)res=res*a; a=a*a; b>>=1; } return res; } int A[N][N]; int f[M][N]; int main() { scanf("%d %d",&n,&m); for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",&A[i][j]); int B=sqrt(m)+1; int K=log2(n); for(int S=0;S<n;S++) { for(int i=0;i<n;i++) { int sum=0; for(int j=0;j<n;j++) { G[j][i]=A[j][i]; if((j|S)==j)sum=myplus(sum,A[j][i]); } Ma[0][i]=sum; Mb[0][i]=((i|S)==i); for(int j=0;j<n;j++) if((j|S)==j)G[j][i]=myplus(G[j][i],sum); } for(int i=1;i<=B;i++)Ma[i]=Ma[i-1]*G; G=Pow(G,B); for(int i=1;i<=B;i++)Mb[i]=G*Mb[i-1]; for(int i=0;i<m;i++)f[i+1][S]=Ma[i%B]*Mb[i/B]; } int ans=0; for(int E=1;E<=m;E++) { for(int i=0;i<K;i++) for(int j=0;j<n;j++) if((j>>i)%2==0)f[E][j]=myplus(f[E][j],mod-f[E][j^(1<<i)]); for(int i=0;i<n;i++)ans^=f[E][i]; } cout<<ans; return 0; } ```