块的计数
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 455 Solved: 261
[Submit][Status][Discuss]
Description
小Y最近从同学那里听说了一个十分牛B的高级数据结构——块状树。听说这种数据结构能在sqrt(N)的时间内维护树上的各种信息,十分的高效。当然,无聊的小Y对这种事情毫无兴趣,只是对把树分块这个操作感到十分好奇。他想,假如能把一棵树分成几块,使得每个块中的点数都相同该有多优美啊!小Y很想知道,能有几种分割方法使得一棵树变得优美。小Y每次会画出一棵树,但由于手速太快,有时候小Y画出来的树会异常地庞大,令小Y感到十分的苦恼。但是小Y实在是太想知道答案了,于是他找到了你,一个天才的程序员,来帮助他完成这件事。
Input
第一行一个正整数N,表示这棵树的结点总数,接下来N-1行,每行两个数字X,Y表示编号为X的结点与编号为Y的结点相连。结点编号的范围为1-N且编号两两不同。
Output
一行一个整数Ans,表示所求的方案数。
Sample Input
1 2
2 3
2 4
4 5
5 6
Sample Output
HINT
100%的数据满足N<=1000000。
Source
首先随便选一个根进行dfs得到size[x]表示以x为根节点的子树的大小。然后我们假设答案为t,需要判断t是否可行。首先显然需要t|n。
显然每一个块有且仅有一个根,定义为这个块的最高点。然后我们发现一个点x是块的根的必要条件是t|size[x]!这个是显然的。然后我
们统计有多少个size[x]被t整除,如果与n/t相同则合法,否则一定小于n/t,因此一定不合法。
1 #include<cstring> 2 #include<cmath> 3 #include<algorithm> 4 #include<iostream> 5 #include<cstdio> 6 7 #define N 1000007 8 #define ll long long 9 10 using namespace std; 11 inline int read() 12 { 13 int x=0,f=1;char ch=getchar(); 14 while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘)f=-1;ch=getchar();} 15 while (ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} 16 return x*f; 17 } 18 19 int n,ans; 20 int Head[N],ret[N<<1],Next[N<<1],tot; 21 int size[N],st[N]; 22 23 inline void ins(int u,int v) 24 { 25 ret[++tot]=v; 26 Next[tot]=Head[u]; 27 Head[u]=tot; 28 } 29 void dfs(int u,int f) 30 { 31 size[u]=1; 32 for (int i=Head[u];i;i=Next[i]) 33 { 34 if (ret[i]==f) continue; 35 dfs(ret[i],u); 36 size[u]+=size[ret[i]]; 37 } 38 st[size[u]]++; 39 } 40 int main() 41 { 42 n=read(); 43 for (int i=1;i<n;i++) 44 { 45 int u=read(),v=read(); 46 ins(u,v);ins(v,u); 47 } 48 dfs(1,0); 49 for (int i=1;i<=n;i++) 50 if (n%i==0) 51 { 52 int sum=0; 53 for (int j=i;j<=n;j+=i) 54 sum+=st[j]; 55 if (sum==n/i) ans++; 56 } 57 printf("%d\n",ans); 58 }