hdu 5329 Question for the Leader

题意:

给出一个有n个点的图,这个图是由一个基环 + 若干外向树组成,问能否把这个图分成 k个 大小为n/k 的 连通的子图,问k有多少种。

限制:

1 <= n <= 1e5

思路:

主要是一个性质:

对于一棵树,如果可以把这棵树分成大小都为k的n/k份,那子树大小是k的倍数的节点恰好有n/k个。(任意选定一个根)

详细见多校官方题解

http://blog.sina.com.cn/u/5657719201

/*hdu 5329 Question for the Leader
  题意:
  给出一个有n个点的图,这个图是由一个基环 + 若干外向树组成,问能否把这个图分成 k个 大小为n/k 的 连通的子图,问k有多少种。
  限制:
  1 <= n <= 1e5
  思路:
  主要是一个性质:
  对于一棵树,如果可以把这棵树分成大小都为k的n/k份,那子树大小是k的倍数的节点恰好有n/k个。(任意选定一个根)
  详细见多校官方题解
 */
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
#define PB push_back
const int N = 1e5 + 5;
int a[N];

int cir[N], cir_tot;
bool in_cir[N];

int tree_sz[N];
int cnt[N];

vector<int> G[N];

int fa[N];
void init_bcj(int n) {
	for(int i = 0; i <= n; ++i)
		fa[i] = i;
}
int get_fa(int x) {
	if(x != fa[x]) return fa[x] = get_fa(fa[x]);
	return x;
}

int dfs(int u, int fa) {
	tree_sz[u] = 1;
	for(int i = 0; i < G[u].size(); ++i) {
		int ch = G[u][i];
		if(ch == fa || in_cir[ch]) continue;
		tree_sz[u] += dfs(ch, u);
	}
	return tree_sz[u];
}

int sum[N], sum_cnt[N];
bool ok(int bei, int have, int n) {
	for(int i = 0; i < bei; ++i)
		sum_cnt[i] = 0;
	sum[0] = tree_sz[cir[0]] % bei;
	++sum_cnt[sum[0]];
	for(int i = 1; i < cir_tot; ++i) {
		sum[i] = (sum[i - 1] + tree_sz[cir[i]]) % bei;
		++sum_cnt[sum[i]];
	}
	if(sum_cnt[0] + have == n / bei) return true;
	int last = cir_tot - 1;
	for(int i = 0; i < cir_tot - 1; ++i) {
		--sum_cnt[sum[i]];
		int tmp = sum[i];
		sum[i] = (sum[last] + tree_sz[cir[i]]) % bei;
		++sum_cnt[sum[i]];
		if(sum_cnt[tmp] + have == n / bei) return true;
		last = i;
	}
	return false;
}

void gao(int n) {
	cir_tot = 0;
	for(int i = 1; i <= n; ++i) {
		G[i].PB(a[i]);
		G[a[i]].PB(i);
		int fx = get_fa(i);
		int fy = get_fa(a[i]);
		if(fx != fy) fa[fy] = fx;
		else if(cir_tot == 0){
			cir[cir_tot++] = i;
			in_cir[i] = 1;
		}
	}

	int nxt = a[cir[0]];
	while(nxt != cir[0]) {
		cir[cir_tot++] = nxt;
		in_cir[nxt] = 1;
		nxt = a[nxt];
	}

	for(int i = 1; i <= n; ++i) {
		if(in_cir[i]) dfs(i, -1);
	}

	for(int i = 1; i <= n; ++i)
		if(!in_cir[i]) ++cnt[tree_sz[i]];

	for(int i = 1; i <= n; ++i) {
		for(int j = 2 * i; j <= n; j += i) {
			cnt[i] += cnt[j];
		}
	}

	int ans = 0;
	for(int i = 1; i <= n; ++i) {
		if(n % i) continue;
		if(ok(i, cnt[i], n)){
			++ans;
		}
	}
	printf("%d\n", ans);
}

void init(int n) {
	init_bcj(n);
	memset(in_cir, 0, sizeof(in_cir));
	memset(tree_sz, 0, sizeof(tree_sz));
	memset(cnt, 0, sizeof(cnt));
	for(int i = 0; i <= n; ++i)
		G[i].clear();
}

int main() {
	int n;
	while(scanf("%d", &n) != EOF) {
		init(n);
		for(int i = 1; i <= n; ++i){
			scanf("%d", &a[i]);
		}
		gao(n);
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-10 09:48:58

hdu 5329 Question for the Leader的相关文章

hdu5329(2015多校4)--Question for the Leader

题目链接:点击打开链接 题目大意:给出一个图,有n条点,n条边,如果要将这个图分为相同点数的k份,要求每一份内部都可以相互链接,那么一共会有几个k符合条件. 1.有一个定理,如果一颗树要分成k个节点一份的子树,那么有n/k个节点所对应子树的节点数是k的倍数. 根据上面这个定理,那么我们就可以计算一颗树能不能被分成n/k份,题目中给出了是一棵树+一条边,所以最终应该是一个环和以环上节点为根的子树,如果环上消除一条边,那么就变成了一颗树,就可以使用定理来判断了. 首先找出环上的节点,和以节点为根的子

是否通过技术任霆发够使肌肤

http://www.gome.com.cn/search?question=%E5%8F%B0%E5%B7%9E%E6%96%B0%E6%A1%A5%E9%95%87%e6%89%be%e5%b0%8f%e5%a7%90%e4%b8%8a%e9%97%a8%e6%9c%8d%e5%8a%a11858885v7572 http://www.gome.com.cn/search?question=%E5%8F%B0%E5%B7%9E%E6%96%B0%E6%A1%A5%E9%95%87%e6%89

榔举料昧卣pn5vu85bwh7a68krk

新华社瓦莱塔4月10日电(记者李拯宇 李佳)全国政协主席俞正声10日在前往非洲三国进行正式友好访问途中过境马耳他,在瓦莱塔会见马耳他议长法鲁贾. 俞正声说,中马保持长期友好关系,政治上相互信任,经济上密切合作,人文交流不断深化.中方感谢马方在中国撤侨行动中给予的支持和帮助.中方愿同马方一道,落实两国领导人达成的共识,弘扬中马传统友好,拓展在科技.渔业.旅游等领域互利合作,打造合作新亮点.中国全国政协愿与马耳他议会和社会各界保持密切交往,加强治国理政经验交流,为两国扩大务实合作营造良好环境,共同促

hdu 5378 Leader in Tree Land(dp+逆元)

题目链接:hdu 5378 Leader in Tree Land 问题可以理解成N个节点的树,有K个ministers的概率,最后乘上N!.每个节点为ministers的概率即为1 / son(以该节点为根节点的子树包含的节点个数),同样不为ministers的概率为(son-1)/son.所以没有必要考虑树的结构,直接根句子节点的个数转移dp[i][j] dp[i][j] = dp[i-1][j-1] * 1 / son[u] dp[i][j] = dp[i-1][j] * (son[u]-

HDU 5793 A Boring Question (费马小定理) ---2016杭电多校联合第六场

A Boring Question Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 156    Accepted Submission(s): 72 Problem Description There are an equation.∑0≤k1,k2,?km≤n∏1?j<m(kj+1kj)%1000000007=?We define t

HDU 5378 Leader in Tree Land

可以用求概率的思想来解决这个问题.令以i号节点为根的子树为第i棵子树,设这颗子树恰好有sz[i]个点.那么第i个点是第i棵子树最大值的概率为1/sz[i],不是最大值的概率为(sz[i]-1)/sz[i].现在可以求解恰好有k个最大值的概率. 令dp[i][j]表示考虑编号从1到i的点,其中恰好有j个点是其子树最大值的概率. 很容易得到如下转移方程:dp[i][j]=dp[i-1][j]*(sz[i]-1)/sz[i]+dp[i-1][j-1]/sz[i].这样dp[n][k]就是所有点中恰好有

HDU 5378 Leader in Tree Land(2015 多校第7场 dp)

Leader in Tree Land Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 150    Accepted Submission(s): 54 Problem Description Tree land has  cities, connected by  roads. You can go to any city from

HDU 5793 A Boring Question (找规律 : 快速幂+乘法逆元)

A Boring Question Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 865    Accepted Submission(s): 534 Problem Description There are an equation.∑0≤k1,k2,?km≤n∏1?j<m(kj+1kj)%1000000007=?We define

HDU 5378 Leader in Tree Land 树形背包

链接 题解来源:点击打开链接 题意: 给定n k 下面n-1行给出一棵树. 把数字1-n填到树的节点上. 填完后计算leader节点个数,若这个点是leader,则这个点上填的数>这个点的子树上填的数 问:恰好有k个leader节点的 填涂方案数. 思路: dp[i][j]表示以i点为根的子树 有恰好j个leader的方案数. 如果u 是叶子节点则 dp[u][0] = 0, dp[u][1] = 1; 如果u不是叶子节点: 先不考虑u点能否成为leader,背包一下. 然后考虑u点:若u能成为