4401: 块的计数
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 414 Solved: 231
[ 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
6
1 2
2 3
2 4
4 5
5 6
Sample Output
3
结论题:
①如果块的大小确定,方案数不会超过1种
②假设块的大小为x,某个节点可以作为一个块的根,当且仅当该节点子树大小是x的倍数
③再假设整棵树的大小为n,如果满足②的节点个数等于n/x个,那么存在分割方法,否则不存在
(为什么不是大于等于n/x个,因为不可能出现大于的情况)
#include<stdio.h>
#include<vector>
using namespace std;
vector<int> G[1000005];
int size[1000005], cnt[1000005];
void Sech(int u, int p)
{
int i, v;
size[u] = 1;
for(i=0;i<G[u].size();i++)
{
v = G[u][i];
if(v==p)
continue;
Sech(v, u);
size[u] += size[v];
}
cnt[size[u]]++;
}
int main(void)
{
int n, i, x, y, j, ans;
scanf("%d", &n);
for(i=1;i<=n-1;i++)
{
scanf("%d%d", &x, &y);
G[x].push_back(y);
G[y].push_back(x);
}
Sech(1, 0);
ans = 0;
for(i=1;i<=n;i++)
{
for(j=i*2;j<=n;j+=i)
cnt[i] += cnt[j];
if(i*cnt[i]>=n)
ans++;
}
printf("%d\n", ans);
return 0;
}