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 ...
随机推荐
- linux应用之samba服务的安装及配置(centos)
一.安装方式: 本文通过yum来重新进行Samba服务器的安装与配置. 二.Samba的简介: Samba是一个能让Linux系统应用Microsoft网络通讯协议的软件,而SMB是Server Me ...
- cassandra 存储二进制data
Blob type The Cassandra blob data type represents a constant hexadecimal number defined as 0[xX](hex ...
- hdu 3507 Print Article —— 斜率优化DP
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3507 设 f[i],则 f[i] = f[j] + (s[i]-s[j])*(s[i]-s[j]) + m ...
- POJ3261(后缀数组+2分枚举)
Milk Patterns Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 12972 Accepted: 5769 Ca ...
- ubuntu12.04下有线网无电缆插入问题
解决方案: 1.查看是否没装网卡驱动: 2.检查网卡是否损坏: 3.检查网线是否损坏(注意:有时候不一定是网线损坏了,而是网线太细了,导通性不好.本人用细网线试了一下,windows下面可以连接网络, ...
- wannafly test D
题意: 给定n,m求满足: 1.a[i][j]互不相同,且有$1<=a[i][j]<=n*m$ 2.对于$a[i1][j1],a[i2][j2]$,如果有 $i1 \oplus j1 &g ...
- CF-805C
C. Find Amir time limit per test 1 second memory limit per test 256 megabytes input standard input o ...
- c++中虚函数与纯虚函数的区别(转)
首先:强调一个概念定义一个函数为虚函数,不代表函数为不被实现的函数.定义他为虚函数是为了允许用基类的指针来调用子类的这个函数.定义一个函数为纯虚函数,才代表函数没有被实现.定义纯虚函数是为了实现一个接 ...
- wmware7安装xp错误:虚拟CPU已经入关闭状态
wm7安装xp错误提示: 虚拟CPU已经入关闭状态.这会造成物理计算机重新启动.这可能是虚拟机操作系统的错误或VMware Workstation软件中的一个配置不正确. 这种情是硬盘模式为AHCI模 ...
- Android-毛笔的探索与开发
前言 这篇文章主要是关于移动端毛笔的开发,在平板上有着书写毛笔字贴的效果. 介绍关于毛笔的算法思路. 项目github地址 算法思路分析 曲线拟合算法 利用曲线拟合算法增加虚拟的点,使得笔迹更加光滑 ...