题面:
有n个格子,每个格子里可能有0/1/2三个数,共3^n中可能。
0和1在一起,剩下的是0
1和2在一起,剩下的是1
2和0在一起,剩下的是2
若两数相同,则原来在这个格子里的数存在,另一个消失
m次操作:
1 u v 把v号格子里的数放到u号格子,v号格子消失,
u,v里的数满足一上条件
2 u 询问使原来u号格子里的数存在的方案数(mod
998244353)
注:操作一是永久影响
n,q<=2e5
input:
3 5
2 1
1 2 1
2 1
1 2 3
2 1
output:
27
9
6
这道题可以用带权并查集来写,权记录概率。
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define mod 998244353
using namespace std;
int n,m,cnt;
int fa[400005];
ll w[400005];
inline void in(int &n){
n=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0'&&c<='9') n=n*10+c-'0',c=getchar();
return ;
}
inline ll calc(ll x,int k){
ll tmp=1;
while(k){
if(k&1) tmp=tmp*x%mod;
x=x*x%mod;
k>>=1;
}
return tmp;
}
int Find(int x){
if(fa[x]==x) return x;
int fath=Find(fa[x]);
w[x]=w[x]*w[fa[x]]%mod;
return fa[x]=fath;
}
int main(){
in(n),in(m);
for(int i=1;i<=2*n;i++) fa[i]=i,w[i]=1;
int op,u,v;
cnt=n;
ll ni=calc(3,mod-2);
ll ci=calc(3,n);
while(m--){
in(op);
if(op==1){
in(u),in(v);
int uu=Find(u),vv=Find(v);
w[uu]=ni*2%mod;
w[vv]=ni;
fa[uu]=fa[vv]=++cnt;
}
else{
in(u);
Find(u);
printf("%lld\n",ci*w[u]%mod);
}
}
return 0;
}
AC代码
可是op1那里改成这样
if(op==1){
in(u),in(v);
w[Find(u)]=ni*2%mod;
w[Find(v)]=ni;
fa[Find(u)]=fa[Find(v)]=++cnt;
}
就不对了!!?? 求解释