#二进制拆分,矩阵乘法#洛谷 6569 [NOI Online #3 提高组] 魔法值

题目


分析

考虑一个点的权值能被统计到答案当且仅当其到1号点的路径条数为奇数条。

那么设 \(dp[i][x][y]\) 表示从 \(x\)\(y\)\(i\) 步路径条数的奇偶性,

这个可以用矩阵乘法加速,多组询问直接二进制拆分预处理出来即可。

大概就是 \(C[x][y]\) 对所有的 \(A[x][z]*B[z][y]\) 取异或


代码

#include <cstdio>
#include <cctype>
using namespace std;
const int N=100;
typedef unsigned uit;
struct maix{
	bool p[N][N];
}A[32],ANS;
uit a[N]; int n,m,Q;
uit iut(){
	uit ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
}
void print(uit ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
maix mul(maix A,maix B,int t){
	maix C;
	for (int i=0;i<t;++i)
	for (int j=0;j<n;++j){
		C.p[i][j]=0;
		for (int k=0;k<n;++k)
		    C.p[i][j]|=A.p[i][k]&B.p[k][j];
	}
	return C;
}
int main(){
	n=iut(),m=iut(),Q=iut();
	for (int i=0;i<n;++i) a[i]=iut();
	for (int i=1;i<=m;++i){
		int x=iut()-1,y=iut()-1;
		A[0].p[x][y]=A[0].p[y][x]=1;
	}
	for (int i=1;i<32;++i) A[i]=mul(A[i-1],A[i-1],n);
	for (int i=1;i<=Q;++i){
		uit x=iut(),ans=0; ANS.p[0][0]=1;
		for (int j=1;j<n;++j) ANS.p[0][j]=0;
		for (int j=31;~j;--j)
		    if ((x>>j)&1) ANS=mul(ANS,A[j],1);
		for (int j=0;j<n;++j) if (ANS.p[0][j]) ans^=a[j];
		print(ans),putchar(10);
	}
	return 0;
}
posted @ 2022-02-25 16:00  lemondinosaur  阅读(73)  评论(0)    收藏  举报