首先赞一下题目, 好题

题意:

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 [LiRi]. 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的更多相关文章

  1. zoj 3820(2014牡丹江现场赛B题)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5374 思路:题目的意思是求树上的两点,使得树上其余的点到其中一个点的 ...

  2. 2014 牡丹江现场赛 A.Average Score(zoj 3819) 解题报告

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5373 题目意思: 有两个class:A 和 B,Bob 在 Clas ...

  3. 2014 牡丹江现场赛 i题 (zoj 3827 Information Entropy)

    I - Information Entropy Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %l ...

  4. 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 ...

  5. zoj 3819(2014牡丹江现场赛 A题 )

    题意:给出A班和B班的学生成绩,如果bob(A班的)在B班的话,两个班级的平均分都会涨.求bob成绩可能的最大,最小值. A班成绩平均值(不含BOB)>A班成绩平均值(含BOB) &&a ...

  6. 2014西安现场赛F题 UVALA 7040

    地址 题意:求在m种颜色中挑选k种颜色,给n个花朵涂色有几种方法. 分析:画图可以发现,基本的公式就是k ×(k-1)^(n-1).但这仅保证了相邻颜色不同,总颜色数不超过k种,并没有保证恰好出现k种 ...

  7. CF GYM100548 (相邻格子颜色不同的方案数 2014西安现场赛F题 容斥原理)

    n个格子排成一行,有m种颜色,问用恰好k种颜色进行染色,使得相邻格子颜色不同的方案数. integers n, m, k (1 ≤n, m ≤ 10^9, 1 ≤ k ≤ 10^6, k ≤ n, m ...

  8. ZOJ 3827 Information Entropy(数学题 牡丹江现场赛)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do? problemId=5381 Information Theory is one of t ...

  9. 【解题报告】牡丹江现场赛之ABDIK ZOJ 3819 3820 3822 3827 3829

    那天在机房做的同步赛,比现场赛要慢了一小时开始,直播那边已经可以看到榜了,所以上来就知道A和I是水题,当时机房电脑出了点问题,就慢了好几分钟,12分钟才A掉第一题... A.Average Score ...

随机推荐

  1. redis配置cluster分布式集群

    #下载最新的redis5. wget http://download.redis.io/releases/redis-5.0.3.tar.gz .tar.gz cd redis- make make ...

  2. DOM、SAX、JDOM、DOM4J以及PULL在XML文件解析中的工作原理以及优缺点对比

    1. DOM(Document Object Model)文档对象模型1. DOM是W3C指定的一套规范标准,核心是按树形结构处理数据,DOM解析器读入XML文件并在内存中建立一个结构一模一样的&qu ...

  3. 推荐SQL Server Management Studio以及Visual Studio下的免费的插件 ApexSQL Complete

    SQL Server 并没有代码格式化的工具,对于处理他人编写的长SQL需要手工的格式化是一件麻烦的事情. 推荐SQL Server Management Studio以及Visual Studio下 ...

  4. iOS-MVC设计模式不足

    View 的最大的任务就是向 Controller 传递用户动作事件. ViewController 不再承担一切代理和数据源的职责,通常只负责一些分发和取消网络请求以及一些其他的任务. 1.1 苹果 ...

  5. 如何用Jquery做图片展示效果

    一. 前言 到底用JQuery做出怎样的展示效果? 让我们先来看一下!网页加载时,如图所示: 二.本人思路 这个效果初学者看起来好像有点复杂,其实不太难,关键是理清思路,从后端的数据库中找出我们要展示 ...

  6. 大数据学习——kafka+storm+hdfs整合

    1 需求 kafka,storm,hdfs整合是流式数据常用的一套框架组合,现在 根据需求使用代码实现该需求 需求:应用所学技术实现,kafka接收随机句子,对接到storm中:使用storm集群统计 ...

  7. POJ-3481 Double Queue,Treap树和set花式水过!

                                                    Double Queue 本打算学二叉树,单纯的二叉树感觉也就那几种遍历了, 无意中看到了这个题,然后就 ...

  8. 九度oj 题目1035:找出直系亲属

    题目描述:     如果A,B是C的父母亲,则A,B是C的parent,C是A,B的child,如果A,B是C的(外)祖父,祖母,则A,B是C的grandparent,C是A,B的grandchild ...

  9. Access denied for user ''@'localhost' to database 'mysql'

    ERROR 1044 (42000): Access denied for user ''@'localhost' to database 'mysql'   在centos下安装好了mysql,用r ...

  10. BZOJ 1800: [Ahoi2009]fly 飞行棋【暴力】

    Description 给出圆周上的若干个点,已知点与点之间的弧长,其值均为正整数,并依圆周顺序排列. 请找出这些点中有没有可以围成矩形的,并希望在最短时间内找出所有不重复矩形. Input 第一行为 ...