B. Apple Tree 暴力 + 数学
http://codeforces.com/problemset/problem/348/B
注意到如果顶点的数值确定了,那么它分下去的个数也就确定了,那么可以暴力枚举顶点的数值。
顶点的数值是和LCM相隔的,LCM就是,比如1有三个子节点,那么1的数值起码都是3的倍数,不然不能整除。
同理,1有三个儿子2、3、4、,如果3有三个儿子,那么1就要起码是9的倍数了,因为需要分给3的时候至少是3.
所以算出整颗树的LCM,叶子节点LCM是1,其他的LCM = lcm(所有子节点) * son[cur]
算出这个后,就可以暴力枚举顶点1的值了,每次枚举都dfs一次,有点暴力1700ms,学学正解先。
注意一点的就是LCM会爆LL,这个时候直接输出sum即可
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 1e5 + ;
int a[maxn];
LL sum;
struct Node {
int u, v, tonext;
}e[maxn * ];
int first[maxn], num;
void addEdge(int u, int v) {
++num;
e[num].u = u, e[num].v = v, e[num].tonext = first[u];
first[u] = num;
}
int vis[maxn], DFN = ;
int son[maxn];
void findSon(int cur) {
for (int i = first[cur]; i; i = e[i].tonext) {
int v = e[i].v;
if (vis[v] == DFN) continue;
vis[v] = DFN;
son[cur]++;
findSon(v);
}
}
LL ans = 1e18L, tans;
LL LCM;
LL lcm(LL a, LL b) {
return a / __gcd(a, b) * b;
}
bool flag;
void dfs(int cur, LL val) {
if (flag) return;
if (son[cur] == ) {
if (val > a[cur]) {
flag = true;
return;
}
tans += a[cur] - val;
return;
}
for (int i = first[cur]; i; i = e[i].tonext) {
int v = e[i].v;
if (vis[v] == DFN) continue;
vis[v] = DFN;
if (val % son[cur] != ) {
flag = true;
return;
}
dfs(v, val / son[cur]);
}
}
LL calc(int cur) {
if (son[cur] == ) return ;
LL thisLCM = ;
for (int i = first[cur]; i; i = e[i].tonext) {
int v = e[i].v;
if (vis[v] == DFN) continue;
vis[v] = DFN;
thisLCM = lcm(thisLCM, calc(v));
}
if (thisLCM > sum / son[cur]) {
printf("%I64d\n", sum);
exit();
}
return son[cur] * thisLCM;
}
void work() {
int n;
scanf("%d", &n);
LCM = ;
for (int i = ; i <= n; ++i) {
scanf("%d", &a[i]);
sum += a[i];
}
for (int i = ; i <= n - ; ++i) {
int u, v;
scanf("%d%d", &u, &v);
addEdge(u, v);
addEdge(v, u);
}
vis[] = DFN;
findSon();
++DFN;
vis[] = DFN;
LCM = calc();
// cout << LCM << endl;
ans = sum;
sum /= LCM;
sum *= LCM;
for (LL i = sum; i >= LCM; i -= LCM) {
++DFN, tans = ;
flag = false;
// dfs(1, 24);
vis[] = DFN;
dfs(, i);
if (flag) continue;
printf("%I64d\n", ans - i);
return;
}
printf("%I64d\n", ans);
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
work();
return ;
}
因为已经知道根节点的值是LCM、2 * LCM、3 * LCM、..... sum中合法的最大的哪一个,那么可以二分答案。
一开始想把她们全部存入vector再二分,但是发现不用,直接二分id就行,就是二分LCM上面的那个倍数就可以了。
500ms
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 1e5 + ;
int a[maxn];
LL sum;
struct Node {
int u, v, tonext;
}e[maxn * ];
int first[maxn], num;
void addEdge(int u, int v) {
++num;
e[num].u = u, e[num].v = v, e[num].tonext = first[u];
first[u] = num;
}
int vis[maxn], DFN = ;
int son[maxn];
void findSon(int cur) {
for (int i = first[cur]; i; i = e[i].tonext) {
int v = e[i].v;
if (vis[v] == DFN) continue;
vis[v] = DFN;
son[cur]++;
findSon(v);
}
}
LL ans = 1e18L, tans;
LL LCM;
LL lcm(LL a, LL b) {
return a / __gcd(a, b) * b;
}
bool flag;
void dfs(int cur, LL val) {
if (flag) return;
if (son[cur] == ) {
if (val > a[cur]) {
flag = true;
return;
}
tans += a[cur] - val;
return;
}
for (int i = first[cur]; i; i = e[i].tonext) {
int v = e[i].v;
if (vis[v] == DFN) continue;
vis[v] = DFN;
if (val % son[cur] != ) {
flag = true;
return;
}
dfs(v, val / son[cur]);
}
}
LL calc(int cur) {
if (son[cur] == ) return ;
LL thisLCM = ;
for (int i = first[cur]; i; i = e[i].tonext) {
int v = e[i].v;
if (vis[v] == DFN) continue;
vis[v] = DFN;
thisLCM = lcm(thisLCM, calc(v));
}
if (thisLCM > sum / son[cur]) {
printf("%I64d\n", sum);
exit();
}
return son[cur] * thisLCM;
}
void work() {
int n;
scanf("%d", &n);
LCM = ;
for (int i = ; i <= n; ++i) {
scanf("%d", &a[i]);
sum += a[i];
}
for (int i = ; i <= n - ; ++i) {
int u, v;
scanf("%d%d", &u, &v);
addEdge(u, v);
addEdge(v, u);
}
vis[] = DFN;
findSon();
++DFN;
vis[] = DFN;
LCM = calc();
// cout << LCM << endl;
ans = sum;
sum /= LCM;
sum *= LCM;
LL be = , en = sum / LCM;
while (be <= en) {
LL mid = ((be + en) >> );
++DFN, flag = false;
vis[] = DFN;
dfs(, mid * LCM);
if (flag) {
en = mid - ;
} else be = mid + ;
}
cout << ans - LCM * en << endl;
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
work();
return ;
}
B. Apple Tree 暴力 + 数学的更多相关文章
- cf202-div 1-B - Apple Tree:搜索,数论,树的遍历
http://codeforces.com/contest/348/problem/B B. Apple Tree time limit per test 2 seconds memory l ...
- POJ 2486 Apple Tree
好抽象的树形DP......... Apple Tree Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6411 Accepte ...
- poj 3321:Apple Tree(树状数组,提高题)
Apple Tree Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 18623 Accepted: 5629 Descr ...
- poj 3321 Apple Tree dfs序+线段树
Apple Tree Time Limit: 2000MS Memory Limit: 65536K Description There is an apple tree outsid ...
- [poj3321]Apple Tree(dfs序+树状数组)
Apple Tree Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 26762 Accepted: 7947 Descr ...
- POJ 3321 Apple Tree(树状数组)
Apple Tree Time Limit: 2000MS Memory Lim ...
- 【HDU 4925】BUPT 2015 newbie practice #2 div2-C-HDU 4925 Apple Tree
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=102419#problem/C Description I’ve bought an or ...
- POJ 3321 Apple Tree(DFS序+线段树单点修改区间查询)
Apple Tree Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 25904 Accepted: 7682 Descr ...
- URAL 1018 Binary Apple Tree(树DP)
Let's imagine how apple tree looks in binary computer world. You're right, it looks just like a bina ...
随机推荐
- iap 应用内购买相关的解释
应用范围app Store Review Guidelines : https://developer.apple.com/app-store/review/guidelines/ 中 11.12 ...
- jquery之extend
jquery的extend方法的用法1. [代码][JavaScript]代码 01<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01// ...
- PHP截取中英文混合字符
<?php //////////////////////////////////////////////////////////////////// // PHP截取中英文及标点符号混合的字符串 ...
- hdu 6053(To my boyfriend)
-----------题目链接------------- 题目描述: 给定一个矩阵,定义\(f(A)\) 为矩阵中不同元素的个数.现在要求\(f(A)\)的期望. 解法: 首先来暴力的,复杂度大约:\ ...
- 谈谈嵌套for循环的理解
谈谈嵌套for循环的理解 说for的嵌套,先说一下一个for循环的是怎么用的. 这次的目的是为了用for循环输出一个乘法口诀表,一下就是我的一步步理解. 一. 语法: ...
- python 函数定义
我们可以创建一个函数来列出费氏数列 >>> def fib(n): # write Fibonacci series up to n ... """Pr ...
- a标签无法传递中文参数问题的解决
a标签无法传递中文参数问题的解决. 可以通过form表单提交 隐藏域的方法解决. 前台jsp页面: <a class="vsb_buton" href="javas ...
- [ZJOI 2012] 网络
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2816 [算法] 对每种颜色的边建一棵LCT , 维护联通性即可 时间复杂度 : O( ...
- FFT的常数优化
卡得一手好常数..学习了..(似乎只对FFT有效) JZOJ 4349 #include <bits/stdc++.h> #define LL long long #define DB l ...
- 创建cube 维度层次
http://blog.programmingsolution.net/ssas-2008/period-dimension-time-dimension-creation-with-year-mon ...