【HDU - 5468】Puzzled Elena(容斥原理,dfs序,数学,素因子分解,有坑)
題干:
|   Problem Description Since both Stefan and Damon fell in love with Elena, and it was really difficult for her to choose. Bonnie, her best friend, suggested her to throw a question to them, and she would choose the one who can solve it. ? ?Input There are multiply tests (no more than 8). ? ?Output For each test, at first, please output "Case #k: ", k is the number of test. Then, please output one line with n numbers (separated by spaces), representing the answer of each vertex. ? ?Sample Input ?5 1 2 1 3 2 4 2 5 6 2 3 4 5 ? ?Sample Output ?Case #1: 1 1 0 0 0  | 
題目大意:
給出一棵樹n個點,每個點上有權值。然后求每棵子樹中與根節點互質,即gcd(a,b)=1的節點個數。
解題報告:
因為1e5以內的每個數的素因子個數不超過10個,所以可以對于每個數的不互素個數可以在O(10*2^10)內算出來,所以直接dfs序映射成一個序列然后按照題意求就行了。注意題目問的是gcd==1而不是互素,所以1和本身也是gcd==1的,所以val==1的時候需要ans++。
貼一個題解:
該題涉及到一個典型問題.問x與數的集合S中有多少個數不互素。解決辦法是將S中所有元素依次進行兩個步驟:①將元素進行質因數分解。②將質因數可能產生的乘積的出現次數加1。最后將x進行質因數分解,利用容斥原理求解。具體方案見代碼。
容斥原理在OJ中常解決兩個典型問題:①求S中有多少個數與x不互素。②求1~m中有多少個數與n不互素。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define F first #define S second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 2e5 + 5; vector<int> vv[MAX]; int val[MAX],ans[MAX],num[MAX]; int dfn[MAX],in[MAX],out[MAX],id; vector<int> fac[MAX]; void db() {for(int tar = 1; tar<MAX; tar++) {int x = tar;for(int i = 2; i*i<=x; i++) {if(x%i == 0) {fac[tar].pb(i);while(x%i==0) x/=i;}}if(x > 1) fac[tar].pb(x);} } int cal(int n,int tar) {int res = 0;int upp = 1<<fac[n].size(),up = fac[n].size();for(int bit = 1; bit<upp; bit++) {int cnt = 0,mul = 1;for(int i = 0; i<up; i++) {if(bit & (1<<i)) {cnt++;mul *= fac[n][i];} }if(cnt & 1) res += num[mul];else res -= num[mul];num[mul] += tar;}return res; } int dfs(int cur,int rt) {int ans1 = cal(val[cur],0);int res = 0;int up = vv[cur].size();for(int i = 0; i<up; i++) {int v = vv[cur][i];if(v == rt) continue;res += dfs(v,cur);}int ans2 = cal(val[cur],1);ans[cur] = res - (ans2 - ans1);if(val[cur] == 1) ans[cur]++;return res+1; } int main() {db();int n,iCase=0;while(~scanf("%d",&n)) {//initid=0;for(int i = 1; i<MAX; i++) num[i] = 0;for(int i = 1; i<=n; i++) vv[i].clear(),ans[i]=0;for(int a,b,i = 1; i<=n-1; i++) {scanf("%d%d",&a,&b);vv[a].pb(b);vv[b].pb(a);} for(int i = 1; i<=n; i++) scanf("%d",val+i);dfs(1,-1);printf("Case #%d:",++iCase);for(int i = 1; i<=n; i++) printf(" %d",ans[i]); printf("\n"); } return 0 ; }?
總結
以上是生活随笔為你收集整理的【HDU - 5468】Puzzled Elena(容斥原理,dfs序,数学,素因子分解,有坑)的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 【CodeForces - 1096D】
 - 下一篇: Win11“离奇”Bug被修复:连接Wi