P6569 [NOI Online #3 提高组]魔法值| 矩阵乘法

题目描述

H 国的交通由 \(n\) 座城市与 \(m\) 条道路构成,城市与道路都从 \(1\) 开始编号,其中 \(1\) 号城市是 H 国的首都。H 国中一条道路将把两个不同城市直接相连,且任意两个城市间至多有一条道路。

H 国是一个信奉魔法的国家,在第 \(j\) 天,\(i\) 号城市的魔法值为 \(f_{i,j}\)​。H 国的魔法师已观测到第 0 天时所有城市的魔法值 \(f_{i,0}\),且他们还发现,之后的每一天每个城市的魔法值,都将会变为所有与该城市直接相连的城市的前一天魔法值的异或值,即

\(f_{x,j}=f_{v_1,j-1}\oplus f_{v_2,j-1}\oplus \cdots\oplus f_{v_k,j-1}\)

其中 \(j\ge 1\)\(v_1,v_2,\cdots,v_k\)​ 是所有与 \(x\) 号城市直接相连的城市,\(\oplus\) 为异或运算。

现在 H 国的国王问了你 \(q\) 个问题,对于第 \(i\)\(1\le i\le q\))个问题你需要回答:第 \(a_i\)​ 天时首都的魔法值是多少。

输入格式

第一行三个用空格分隔的整数 \(n,m,q\),表示城市数、道路数与问题数。

第二行 \(n\) 个用空格分隔的整数,第 iii 个整数表示 \(f_i\)

接下来 \(m\) 行,每行两个用空格分隔的正整数 \(u,v\),表示一条连接 \(u\) 号城市与 \(v\) 号城市的道路。

接下来 \(q\) 行每行一个整数,第 iii 行的整数表示 \(a_i\)​。

输出格式

按顺序输出 \(q\) 行每行一个整数,表示对应问题的答案。


#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define ll long long
int n,m,q;
struct M{
  	ll s[110][110],r,c;
  	void clear(){memset(s,0,sizeof(s));}
}b,f[40];
M operator * (const M &x,const M &y){
	M now; now.clear();
  	now.r=x.r,now.c=y.c;
  	for(int k=1;k<=x.c;k++)
  	for(int i=1;i<=x.r;i++)
  	for(int j=1;j<=y.c;j++)
  	now.s[i][j]^=x.s[i][k]&y.s[k][j];
  	return now;
}
int main(){
  	scanf("%d%d%d",&n,&m,&q);
  	b.clear();
  	b.r=1,b.c=n;
  	f[0].clear();
  	f[0].r=n,f[0].c=n;
  	for(int i=1;i<=n;i++)scanf("%lld",&b.s[1][i]);
  	for(int i=1,u,v;i<=m;i++){
    	scanf("%d%d",&u,&v);
    	f[0].s[u][v]=(1ll<<62)-1;
    	f[0].s[v][u]=(1ll<<62)-1;
  	}
  	for(int i=1;i<=31;i++)f[i]=f[i-1]*f[i-1];
 	ll now;
  	while(q--){
    	scanf("%lld",&now); M ans=b;
    	for(int j=31;j>=0;j--)
     	if(now>=(1ll<<j)){
      		ans=ans*f[j];
			now^=(1ll<<j);
			if(!now)break;
		}		
		printf("%lld\n",ans.s[1][1]);
  	}
}
posted @ 2020-05-25 10:33  白木偶君  阅读(139)  评论(0编辑  收藏  举报