bzoj 4401: 块的计数(结论)

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值