bzoj 4401: 块的计数(结论)

来源:互联网 发布:卫浴软件 编辑:程序博客网 时间:2024/06/06 10:19

4401: 块的计数

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 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;}


原创粉丝点击