Codeforces Round #511 (Div. 1) C. Region Separation(dp + 数论)
题意
一棵 \(n\) 个点的树,每个点有权值 \(a_i\) 。你想砍树。
你可以砍任意次,每次你选择一些边断开,需要满足砍完后每个连通块的权值和是相等的。求有多少种砍树方案。
\(n \le 10^6, a_i \le 10^9\)
题解
先假设只砍一次。令所有点权和为 \(S\) ,那么假设要砍成 \(k\) 个连通块,则每个连通块的权值和均为 \(\displaystyle \frac{S}{k}\) 。
考虑如何得到砍的方案,以 \(1\) 号点为根 \(dfs\) ,若当前点 \(i\) 的子树之和 \(\frac{S}{k} | \displaystyle sum_i\) ,则当前子树可以砍下来。若最后恰好砍了 \(k\) 次,那么就得到了一个合法的砍树方案。
其实这就等价于 \(\displaystyle \sum_{i=1}^{n} [\frac{S}{k} | sum_i] = k\) 。
不难看出这个对应且仅对应一种方案。如果不足 \(k\) ,那么就没有那么多个点可以分;多于 \(k\) 的情况是不可能的,因为总和不够分配。
这个式子还不够优秀,我们转化一下:
[\frac{S}{k}|sum_i] &= [S | k \times sum_i] \\
&= [\frac{S}{\gcd(S,sum_i)}|k \times \frac{sum_i}{\gcd(S,sum_i)}] \\
&\because \frac{S}{\gcd(S,sum_i)} \bot \frac{sum_i}{\gcd(S,sum_i)} \\
&= [\frac{S}{\gcd(S,sum_i)} | k]
\end{align}
\]
然后就变成
\]
显然这个我们可以枚举倍数在 \(O(n \ln n)\) 的时间内解决(注意 \(k \le n\) )
那么如果砍多次呢?可以看出如果第一次砍成了 \(x\) 块,那么第二次砍成的块数 \(y\) 必须满足 \(x|y\) 。
因为你之后的权值只能比之前分的更多,且每个联通块的权值是之前的一个因子。
这部分也可以 \(O(n \ln n)\) 算。
总结
熟悉这种分成很多块有关于 \(O(\ln n)\) 复杂度的东西就行啦qwq
代码
#include <bits/stdc++.h>
#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define debug(x) cout << #x << ": " << (x) << endl
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
using namespace std;
typedef long long ll;
template<typename T> inline bool chkmin(T &a, T b) {return b < a ? a = b, 1 : 0;}
template<typename T> inline bool chkmax(T &a, T b) {return b > a ? a = b, 1 : 0;}
inline int read() {
int x(0), sgn(1); char ch(getchar());
for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1;
for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48);
return x * sgn;
}
void File() {
#ifdef zjp_shadow
freopen ("C.in", "r", stdin);
freopen ("C.out", "w", stdout);
#endif
}
const int N = 1e6 + 1e3;
bitset<N> pass;
ll sum[N], dp[N]; int n, fa[N];
int main () {
File();
n = read();
For (i, 1, n) sum[i] = read();
For (i, 2, n) fa[i] = read();
Fordown (i, n, 1) sum[fa[i]] += sum[i];
For (i, 1, n) {
ll tmp = sum[1] / __gcd(sum[1], sum[i]);
if (tmp <= n) ++ dp[tmp];
}
Fordown (i, n, 1) if (dp[i])
for (int j = i * 2; j <= n; j += i) dp[j] += dp[i];
For (i, 1, n)
pass[i] = (dp[i] == i && !(sum[1] % i)), dp[i] = 0;
dp[1] = pass[1];
ll ans = 0;
For (i, 1, n) if (pass[i]) {
for (int j = i * 2; j <= n; j += i)
if (pass[j]) dp[j] += dp[i];
ans += dp[i];
}
printf ("%lld\n", ans);
return 0;
}
Codeforces Round #511 (Div. 1) C. Region Separation(dp + 数论)的更多相关文章
- Codeforces Round #511 (Div. 2)
Codeforces Round #511 (Div. 2) #include <bits/stdc++.h> using namespace std; int n; int main() ...
- 2018.9.21 Codeforces Round #511(Div.2)
只写了AB,甚至还WA了一次A题,暴露了蒟蒻的本质=.= 感觉考的时候有好多正确或和正解有关的思路,但是就想不出具体的解法或者想的不够深(长)(怕不是过于鶸) 话说CF的E题怎么都这么清奇=.= A. ...
- Codeforces Round #174 (Div. 1) B. Cow Program(dp + 记忆化)
题目链接:http://codeforces.com/contest/283/problem/B 思路: dp[now][flag]表示现在在位置now,flag表示是接下来要做的步骤,然后根据题意记 ...
- Codeforces Round #511 (Div. 2):C. Enlarge GCD(数学)
C. Enlarge GCD 题目链接:https://codeforces.com/contest/1047/problem/C 题意: 给出n个数,然后你可以移除一些数.现在要求你移除最少的数,让 ...
- Codeforces Round #448 (Div. 2) A. Pizza Separation【前缀和/枚举/将圆(披萨)分为连续的两块使其差最小】
A. Pizza Separation time limit per test 1 second memory limit per test 256 megabytes input standard ...
- Codeforces Round #511 (Div. 2)-C - Enlarge GCD (素数筛)
传送门:http://codeforces.com/contest/1047/problem/C 题意: 给定n个数,问最少要去掉几个数,使得剩下的数gcd 大于原来n个数的gcd值. 思路: 自己一 ...
- Codeforces Round #511 Div.1 A Div.2 C
嗯切一题走人很开心. gzy-50分比我还惨. 题意:有n个数,去掉尽量少的数使得剩下数的gcd变大. 首先把这n个数都除以gcd,就变成了去掉尽量少的数使得gcd不等于1. 可以枚举一个质数,然后统 ...
- C. Enlarge GCD Codeforces Round #511 (Div. 2)【数学】
题目: Mr. F has nn positive integers, a1,a2,…,an. He thinks the greatest common divisor of these integ ...
- B. Cover Points Codeforces Round #511 (Div. 2)【数学】
题目: There are nn points on the plane, (x1,y1),(x2,y2),…,(xn,yn)(x1,y1),(x2,y2),…,(xn,yn). You need t ...
随机推荐
- Median String CodeForces - 1144E
You are given two strings ss and tt, both consisting of exactly kk lowercase Latin letters, ss is le ...
- PS绘制扁平化风格相机镜头UI图标
一.新建一个画布,绘制一个460*460图层,圆角半径40像素.填充渐变颜色,加一点点投影,这样就有质感了. 二.接下来我们要来绘制主体部分,绘制一个圆,大小400*400,用内阴影,渐变叠加,投影得 ...
- 关于iframe页面里的重定向问题
最近公司做的一个功能,使用了iframe,父页面内嵌子页面,里面的坑还挺多的,上次其实就遇到过,只不过今天在此描述一下. 请允许我画个草图: 外层大圈是父级页面,里层是子级页面,我们是在父级引用子级页 ...
- CRM系统(第二部分)
阅读目录 一.讲师与学生简介 二. 初始化 ,studyrecord, 三.初始化 course_record:批量生成学习记录 四. 考勤 url跳转 五.录入成绩 六.highcharts表 ...
- HTML,CSS笔记
text-indent 属性规定文本块中首行文本的缩进.允许使用负值.如果使用负值,那么首行会被缩进到左边.p{ text-indent:50px; } HTML <label> 标签的 ...
- PHPUnit实践一(初识)
PHPUnit实践一(初识) 本系列教程所有的PHPUnit测试基于PHPUnit6.5.9版本,Lumen 5.5框架 前置 日常我们的普通用到的测试: 代码直接echo,debug等方法测 ...
- eclipse打开package explorer视图
第一步:window-show view-other 第二步:
- maven+springmvc项目启动时,request mapping not found……
springmvc项目跑的好好的,跑着跑着,出现request mapping not found的问题. 第一波,网上查问题,stackoverflow上面的各种配置说明,但是我本地就是没查出问题 ...
- 如何使用 Yum Repository 安装指定版本的 MySQL
自从从使用 debian 系的 apt-get 转到使用 yum 工具之后一直不是很习惯,也没有去看过很多工具包安装的时候到底影响到了哪些文件等.这次借这次社区版 MySQL 安装来一并梳理一下. 首 ...
- 自定义组件Component
定义compa组件 由4个页面构成 compa.js: compa.json: compa.wxml: compa:wxss: 1.compa.json:在json文件进行自定义组件声明 { &quo ...