ZR 动物园

30分做法:

三进制枚举,暴力模拟即可。

#include<queue>
#include<cstring>
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; typedef long long ll; const ll mo=998244353; const int maxm=2e5+7; int n,m; int f[maxm]; ll w[maxm]; ll tot,inv3; ll qpow(int a,int b) { ll ans=1,base=a; while(b) { if(b&1) ans=ans*base%mo; base=base*base%mo; b>>=1; } return ans; } int find(int x) { if(x!=f[x]) { int father=find(f[x]); if(father!=f[x]) w[x]=w[x]*w[f[x]]%mo;//先不处理根节点的值,防止合并时再计算一次 f[x]=father; } return f[x]; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { f[i]=i; w[i]=1; } tot=qpow(3,n); inv3=qpow(3,mo-2);//1/3在%mo下的乘法逆元 for(int i=1;i<=m;i++) { int opt,u,v; scanf("%d%d",&opt,&u); if(opt==1) { scanf("%d",&v); int fx=find(u); int fy=find(v);//因为使过的不能使,所以不用判fx,fy相等 f[fy]=fx; w[fx]=w[fx]*inv3*2ll%mo; w[fy]=w[fy]*inv3%mo; w[fy]=w[fy]*qpow(w[fx],mo-2)%mo; } else { int fx=find(u); ll ans=w[u]*tot%mo; if(u!=fx) printf("%lld\n",ans*w[fx]%mo); else printf("%lld\n",ans); } } return 0; }

猜你喜欢

转载自www.cnblogs.com/lihan123/p/11740824.html