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]);
}
}
不以物喜,不以己悲

浙公网安备 33010602011771号