这道题说起来挺可惜的,当时纠结是用常数大但有可能减少递归层数的模还是用常数小但递归多的回溯纠结了好半天,最终错误的选择了摸。导致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 }
时间: 2024-10-19 09:24:02