其他分享
首页 > 其他分享> > Codeforces 1654D - Potion Brewing Class

Codeforces 1654D - Potion Brewing Class

作者:互联网

问题:最开始的思路是找到最小的部分,然后根据倍数计算,但是实在不知道怎么比较两个数的大小

答案:其实答案应该是对于每一个点i,i的成分大小应该是对于每一个其他点,比例中分母质数分解使每个质数最大时的乘积(因为需要能整除),但这样得到的结果是O(n^2),所以需要由一个点能直接推到多个点,其实已知一个成分的多少后保留倍数即可推到另外的点。

所以时间复杂度主要在于质因数的预处理。

记得注意fp函数不可以在f一边改的时候一边更新,因为分母分子不一定互质,所以要都改完以后再更新

代码:

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstdio>
  4 #include<queue>
  5 #include<cmath>
  6 typedef long long ll;
  7 #define maxn 200000
  8 using namespace std;
  9 struct ding
 10 {
 11     int to,w1,w2,nex;
 12 }e[4*maxn];
 13 int cnt=0,n,h[2*maxn],prime[2*maxn],id[2*maxn],mini[2*maxn];
 14 vector<int>v[maxn*2];
 15 bool check[2*maxn];
 16 ll ans=0,val;
 17 ll mo=998244353; 
 18 int len,f[2*maxn],fp[2*maxn];
 19 void pre()
 20 {
 21     for (int i=1;i<=maxn;i++) check[i]=false;
 22     for (int i=2;i<=maxn;i++)
 23     {
 24         if (!check[i]) id[i]=len,prime[len++]=i,mini[i]=i;
 25         for (int j=0;j<len;j++)
 26         {
 27             if (i*prime[j]>maxn) break;
 28             check[i*prime[j]]=true;
 29             mini[i*prime[j]]=prime[j];
 30             if (i%prime[j]==0) break;
 31         }
 32     }
 33     for (int i=2;i<=maxn;i++)
 34     {
 35         int now=i;
 36         while (now!=1)
 37         {
 38             v[i].push_back(id[mini[now]]);
 39             now=now/mini[now];
 40         }
 41     }
 42 }
 43 ll poww(ll x,ll t)
 44 {
 45     if (t<0) return poww(poww(x,mo-2),-t);
 46     if (t==0) return 1ll;
 47     ll sum=1ll;
 48     x=x%mo;
 49     for (t;t>0;t=t>>(1ll)) 
 50     {
 51         if (t&(1ll)) sum=(sum*x)%mo;
 52         x=(x*x)%mo;
 53     }
 54     return sum%mo;
 55 }
 56 void add(int x,int y,ll v1,ll v2)
 57 {
 58     e[++cnt].to=y;
 59     e[cnt].w1=v1;
 60     e[cnt].w2=v2;
 61     e[cnt].nex=h[x];
 62     h[x]=cnt;
 63 }
 64 void dfs(int x,int fa)
 65 {
 66     for (int i=h[x];i;i=e[i].nex)
 67     {
 68         if (e[i].to==fa) continue;
 69         int t=e[i].to;
 70         int tot1=v[e[i].w1].size();
 71         int tot2=v[e[i].w2].size();
 72         for (int j=0;j<tot1;j++) --f[v[e[i].w1][j]];
 73         for (int j=0;j<tot2;j++) ++f[v[e[i].w2][j]];
 74         dfs(t,x);
 75         for (int j=0;j<tot1;j++) fp[v[e[i].w1][j]]=min(fp[v[e[i].w1][j]],f[v[e[i].w1][j]]);
 76         for (int j=0;j<tot2;j++) fp[v[e[i].w2][j]]=min(fp[v[e[i].w2][j]],f[v[e[i].w2][j]]);
 77         for (int j=0;j<tot1;j++) f[v[e[i].w1][j]]++;
 78         for (int j=0;j<tot2;j++) f[v[e[i].w2][j]]--;
 79     }
 80 }
 81 void dfs2(int x,ll now,int fa)
 82 {
 83     for (int i=h[x];i;i=e[i].nex)
 84     {
 85         int t=e[i].to;
 86         if (t==fa) continue;
 87         int tot1=v[e[i].w1].size();
 88         int tot2=v[e[i].w2].size();
 89         for (int j=0;j<tot1;j++) now=(now*poww(prime[v[e[i].w1][j]],mo-2))%mo;
 90         for (int j=0;j<tot2;j++) now=(now*prime[v[e[i].w2][j]])%mo;
 91         ans=(ans+now)%mo; 
 92         dfs2(t,now,x);
 93         for (int j=0;j<tot1;j++) now=(now*prime[v[e[i].w1][j]])%mo;
 94         for (int j=0;j<tot2;j++) now=(now*poww(prime[v[e[i].w2][j]],mo-2))%mo;
 95     }
 96 }
 97 int main()
 98 {
 99     int cas,n;
100     cin>>cas;
101     pre();
102     while (cas--)
103     {
104         cin>>n;
105         for (int i=1;i<=n;i++) h[i]=0; 
106         cnt=0;
107         int maxl=0;
108         for (int i=0;i<len;i++)
109         if (prime[i]<=n) maxl++;
110         else break; 
111         maxl=len;
112         //cout<<maxl<<"!"<<endl;
113         for (int i=0;i<maxl;i++) f[i]=fp[i]=0;
114         int x,y;
115         ll v1,v2;
116         for (int i=1;i<n;i++)
117         {
118             scanf("%d%d%lld%lld",&x,&y,&v1,&v2);
119             add(x,y,v1,v2);
120             add(y,x,v2,v1);
121         }
122         dfs(1,0);
123         val=1ll; 
124         for (int i=0;i<maxl;i++) 
125         {
126             //if (-fp[i]!=0) cout<<prime[i]<<" "<<fp[i]<<endl;
127             val=(val*poww(prime[i],-fp[i]))%mo; 
128         }
129         ans=1ll;
130         dfs2(1,1,0);
131         ans=(ans*val)%mo;
132         cout<<ans<<endl;
133     }
134     return 0;
135  } 

 

标签:prime,cnt,Potion,int,ll,Brewing,maxn,include,Class
来源: https://www.cnblogs.com/2014nhc/p/16098870.html