1. 程式人生 > >9.18考試 第一題count題解

9.18考試 第一題count題解

tor 技術分享 n) 方法 i++ fine cstring build vector

技術分享

  這道題說起來挺可惜的,當時糾結是用常數大但有可能減少遞歸層數的模還是用常數小但遞歸多的回溯糾結了好半天,最終錯誤的選擇了摸。導致T了20分,改成回溯就A了。

  先分析一下性質,我在考試的時候打表發現在數據範圍內因子最多有240個,因此有可能是通過枚舉因子進行計算,然後如果說對於一個塊他的確可以把一棵樹分為幾塊方法只有一種(不要問我為什麽,我也不知道怎麽證,但的確如此)那麽我們的最壞復雜度就是O(240*n),比理論最大復雜度還多了一倍,這也是為什麽當時我自己預估60分的原因,然而這就很尷尬了,這的確能過,因為我們只要搜索到一個不合法位置就可以直接return所以會快許多。而且,對於size小於當前check的我們就沒有必要再去搜了,這會降低對於較大因子的時間復雜度。然後就很玄學的過了,額,過了……

技術分享
 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<queue>
 6 #include<algorithm>
 7 #include<cmath>
 8 #include<map>
 9 #include<vector>
10 #define N 1000005
11 using namespace std;
12 int size[N],fa[N],n,a[N];
13 struct ro 14 { 15 int to,next; 16 }road[N*2]; 17 int zz1,zz,sx[N]; 18 void build(int x,int y) 19 { 20 zz++; 21 road[zz].to=y; 22 road[zz].next=a[x]; 23 a[x]=zz; 24 } 25 void dfs(int x) 26 { 27 size[x]=1; 28 for(int i=a[x];i>0;i=road[i].next) 29 { 30 int y=road[i].to;
31 if(y==fa[x])continue; 32 fa[y]=x; 33 dfs(y); 34 size[x]+=size[y]; 35 } 36 } 37 int ans=2; 38 bool yx; 39 int dfs2(int x,int l) 40 { 41 int sum=1; 42 for(int i=a[x];i>0;i=road[i].next) 43 { 44 int y=road[i].to; 45 if(y==fa[x])continue; 46 if(size[y]>=l) 47 { 48 int k=dfs2(y,l); 49 if(k==-1) 50 return -1; 51 sum+=k; 52 } 53 else 54 { 55 sum+=size[y]; 56 } 57 if(sum>l) 58 { 59 return -1; 60 } 61 } 62 if(sum==l) 63 { 64 return 0; 65 } 66 else return sum; 67 } 68 void check(int l) 69 { 70 int k=dfs2(1,l); 71 if(k!=-1) 72 ans++; 73 } 74 int main() 75 { 76 scanf("%d",&n); 77 for(int i=1;i<n;i++) 78 { 79 int x,y; 80 scanf("%d%d",&x,&y); 81 build(x,y); 82 build(y,x); 83 } 84 for(int i=2;i<n;i++) 85 { 86 if(n%i==0) 87 { 88 zz1++; 89 sx[zz1]=i; 90 } 91 } 92 dfs(1); 93 for(int i=1;i<=zz1;i++) 94 check(sx[i]); 95 printf("%d\n",ans); 96 return 0; 97 }
View Code

9.18考試 第一題count題解