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