2014牡丹江 现场赛 F zoj 3824 Fiber-optic Network
首先赞一下题目, 好题
题意:
Marjar University has decided to upgrade the infrastructure of school intranet by using fiber-optic technology. There are N buildings in the school. Each building will be installed
with one router. These routers are connected by optical cables in such a way that there is exactly one path between any two routers.
Each router should be initialized with an operating frequency Fi before it starts to work. Due to the limitations of hardware and environment, the operating frequency
should be an integer number within [Li, Ri]. In order to reduce the signal noise, the operating frequency of any two adjacent routers should be co-prime.
Edward is the headmaster of Marjar University. He is very interested in the number of different ways to initialize the operating frequency. Please write a program to help him! To make
the report simple and neat, you only need to calculate the sum of Fi (modulo 1000000007) in all solutions for each router.
英文自己看。 大概意思就是一棵树上每一个点i能够给一个L[i] ~ R[i]的值, 相邻的两个点的值要互质, 问每一个点的全部情况的值的和, mod 1000000007
大概思路就是枚举一个点, 然后枚举这个点上的值(i)。 然后求出这种情况有多少种(dp[i]), 那么这个点上的答案就是 dp[1] * 1 + dp[2] * 2 + dp[3] * 3 + .........
然后就是树形dp了, 转移方程就是 dp[i][j] =π{(∑{dp[t][k]
| gcd(j, k) == 1}) | i 和 t 相邻}
可是这样转移的复杂度是50 * 50000 * 50000, 就算15秒时限也会超时
所以我们能够考虑用不互质的来转移。
设s[i] = ∑dp[i][j]
那么转移方程就是 dp[i][j] =π{(s[i] - ∑{dp[t][k]
| gcd(j, k) != 1}) | i 和 t 相邻}
对于dp[i][j],我们能够把 j 质因数分解, 如果 j = p1^e1 * p2^e2 * p3^e3。 50000以内的数最多有6个不同的质因数;
然后我们记录一下 div[i][k] = ∑{ dp[i][j] | j 是 k 的倍数}, 这个能够nlogn的复杂度处理出来;
这样 ∑{dp[t][k] | gcd(j, k) != 1} = div[t][p1]
+ div[t][p2] + div[t][p3] - div[t][p1 * p2] - div[t][p1 * p3] - div[t][p2 * p3] + div[t][p1 * p2 * p3],
这样能够用容斥原理算了, 复杂度最多为2 ^ 6;
这样dp一次复杂度大概就是 50
* 50000 * (log50000 + 2^6);
要算50个点的话。
还是会超时;
可是这是一颗树。
对每一个点都dp一次的话算了非常多反复的东西, 所以我们不要每次都去所有dp一次, 比如算完i点的了, 要去算j点的, 如果i j相邻。 那么在dp数组中仅仅有i和j的值有变化。 我们就仅仅要再算这两个点的dp转移就够了。
很多其它细节请看代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <vector> using namespace std; typedef long long LL;
const int N = 50009;
const LL M = 1000000007; inline void addIt(int &a, int b)
{
a += b;
if(a >= M) a -= M;
} inline int sub(int a, int b)
{
a -= b;
if(a < 0) a += M;
if(a >= M) a -= M;
return a;
} struct Num
{
int p[11];
int allp;
}num[N]; struct Data
{
int dp[N], div[N], all;
}data[55], fb[55]; int L[55], R[55];
int ans[55];
int n;
vector<int> e[55];
bool vis[55];
int rcn, rcv; void print()
{
for(int i = 0; i < n; i++)
{
printf("i = %d\n", i);
for(int j = 0; j < 6; j++) printf("dp[%d] = %d\n", j, data[i].dp[j]);
}
} int rc(int i, int xs)
{
int t, r = 0;
for(; i < num[rcn].allp; i++)
{
if(xs * num[rcn].p[i] <= R[rcv]) t = data[rcv].div[xs * num[rcn].p[i]];
else t = 0;
//printf("***%d, t = %d\n", xs * num[rcn].p[i], t);
addIt(r, sub(t, rc(i + 1, xs * num[rcn].p[i])));
}
//printf("r = %d\n", r);
return r;
} void dfsTree(int pre, int now)
{
if(vis[now]) return;
vis[now] = true;
int i, siz = e[now].size();
for(i = 0; i < siz; i++) dfsTree(now, e[now][i]);
if(pre >= 0 && siz <= 1) for(i = L[now]; i <= R[now]; i++) data[now].dp[i] = 1;
else for(i = L[now]; i <= R[now]; i++)
{
data[now].dp[i] = 1;
for(int j = 0; j < siz; j++) if(e[now][j] != pre)
{
rcn = i;
rcv = e[now][j];
data[now].dp[i] = (LL)(data[now].dp[i]) * sub(data[e[now][j]].all, rc(0, 1)) % M;
}
}
data[now].all = 0;
for(i = 1; i <= R[now]; i++)
{
data[now].div[i] = 0;
for(int j = i; j <= R[now]; j += i) if(j >= L[now]) addIt(data[now].div[i], data[now].dp[j]);
if(i >= L[now]) addIt(data[now].all, data[now].dp[i]);
}
} void dfs(int pre, int now, int deep)
{
dfsTree(-1, now);
//if(now == 1) print();
int i, siz = e[now].size();
ans[now] = 0;
for(i = L[now]; i <= R[now]; i++) addIt(ans[now], (LL)data[now].dp[i] * i % M);
//fb[deep] = data[now];
//vis[now] = false;
for(i = 0; i < siz; i++) if(e[now][i] != pre)
{
vis[e[now][i]] = false;
fb[deep] = data[e[now][i]];
vis[now] = false;
dfs(now, e[now][i], deep + 1);
data[e[now][i]] = fb[deep];
vis[e[now][i]] = true;
}
} void init()
{
int i, j, k;
for(i = 0; i < N; i++) num[i].allp = 0;
for(i = 2; i < N; i++) if(num[i].allp == 0) for(j = i; j < N; j += i) num[j].p[num[j].allp++] = i;
} int main()
{
//freopen("13F.in", "r", stdin);
init();
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
int i, j, k;
for(i = 0; i < n; i++)
{
scanf("%d", &L[i]);
}
for(i = 0; i < n; i++)
{
scanf("%d", &R[i]);
e[i].clear();
}
for(i = 0; i < n - 1; i++)
{
scanf("%d %d", &j, &k);
j--;
k--;
e[j].push_back(k);
e[k].push_back(j);
}
memset(vis, false, sizeof(vis));
memset(data, 0, sizeof(data));
dfsTree(-1, 0);
//print();
dfs(-1, 0, 0);
for(i = 0; i < n - 1; i++) printf("%d ", ans[i]); printf("%d\n", ans[i]);
}
return 0;
}
2014牡丹江 现场赛 F zoj 3824 Fiber-optic Network的更多相关文章
- zoj 3820(2014牡丹江现场赛B题)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5374 思路:题目的意思是求树上的两点,使得树上其余的点到其中一个点的 ...
- 2014 牡丹江现场赛 A.Average Score(zoj 3819) 解题报告
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5373 题目意思: 有两个class:A 和 B,Bob 在 Clas ...
- 2014 牡丹江现场赛 i题 (zoj 3827 Information Entropy)
I - Information Entropy Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%lld & %l ...
- zoj 3827(2014牡丹江现场赛 I题 )
套公式 Sample Input 33 bit25 25 50 //百分数7 nat1 2 4 8 16 32 3710 dit10 10 10 10 10 10 10 10 10 10Sample ...
- zoj 3819(2014牡丹江现场赛 A题 )
题意:给出A班和B班的学生成绩,如果bob(A班的)在B班的话,两个班级的平均分都会涨.求bob成绩可能的最大,最小值. A班成绩平均值(不含BOB)>A班成绩平均值(含BOB) &&a ...
- 2014西安现场赛F题 UVALA 7040
地址 题意:求在m种颜色中挑选k种颜色,给n个花朵涂色有几种方法. 分析:画图可以发现,基本的公式就是k ×(k-1)^(n-1).但这仅保证了相邻颜色不同,总颜色数不超过k种,并没有保证恰好出现k种 ...
- CF GYM100548 (相邻格子颜色不同的方案数 2014西安现场赛F题 容斥原理)
n个格子排成一行,有m种颜色,问用恰好k种颜色进行染色,使得相邻格子颜色不同的方案数. integers n, m, k (1 ≤n, m ≤ 10^9, 1 ≤ k ≤ 10^6, k ≤ n, m ...
- ZOJ 3827 Information Entropy(数学题 牡丹江现场赛)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do? problemId=5381 Information Theory is one of t ...
- 【解题报告】牡丹江现场赛之ABDIK ZOJ 3819 3820 3822 3827 3829
那天在机房做的同步赛,比现场赛要慢了一小时开始,直播那边已经可以看到榜了,所以上来就知道A和I是水题,当时机房电脑出了点问题,就慢了好几分钟,12分钟才A掉第一题... A.Average Score ...
随机推荐
- Lex与Yacc学习(四)之Lex规范
Lex规范的结构 lex程序由三部分组成:定义段.规则段和用户子例程序段 ...定义段... %% ...规则段... %% ...用户子例程序段... 这些部分由以两个百分号组成的行分隔开.尽管某一 ...
- Ribbitmq
rittbiMQ: 连接远程rabbitmq server sudo rabbitmqctl addser mihon mihon123 sudo rabbitmqctl set_permission ...
- 【PL/SQL编程基础】
[PL/SQL编程基础]语法: declare 声明部分,例如定义变量.常量.游标 begin 程序编写,SQL语句 exception 处理异常 end: / 正斜杠表示执行程序快范例 -- Cre ...
- python3--__repr_和__str__会返回字符串表达形式
__repr_和__str__会返回字符串表达形式 下一个例子是已经见过的init构造方法和add重载方法,本例也会定义返回实例的字符串表达形式的__repr__方法.字符串格式把self.data对 ...
- POJ-1200 Crazy Search,人生第一道hash题!
Crazy Search 真是不容易啊,人生第一道hash题竟然是搜博客看题解来的. 题意:给你 ...
- BZOJ 1012 [JSOI2008]最大数maxnumber【线段树】
水题,每次记录一下当前有多少个数,然后按照题目所指示的那样模拟就行,每次向线段树末尾插入(其实是修改)题目中指定的数,然后询问当前的个数到前面Q个数中最大值是多少结果就是,好久不碰线段树了,用数组模拟 ...
- spring工作机制及为什么要用?
spring工作机制及为什么要用?1.spring mvc请所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责对请求进行真正的处理工作.2.DispatcherSer ...
- 【loj6029】「雅礼集训 2017 Day1」市场
题目 题意:四种操作,区间加法.区间除法(下取整).区间求最小值.区间求和. 第1.3.4个操作都是摆设,关键在于如何做区间除法. 很明显不能直接把区间的和做除法后向下取整,因为区间和可能会多凑出一个 ...
- php 学习随笔
---恢复内容开始--- round进行格式化数值(进位规则遵守“四舍六入五双”,即前一位是奇数,则进一,前一位是偶数则舍入,因此,rount(1.5)=2,round(2.5)=2,round(0. ...
- Spoj-TRNGL Make Triangle
Make Triangle Chayanika loves Mathematics. She is learning a new chapter geometry. While reading the ...