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;	
}

 

posted @ 2019-10-25 20:55  lihan123  阅读(214)  评论(0编辑  收藏  举报