题目大意

  有一颗树,要为每个节点赋一个值\(l_i\leq a_i\leq r_i\),使得任意相邻的节点互素。然后对每个节点统计\(a_i\)在所有可能的情况中的和。

  \(n\leq 50,1\leq l_i\leq r_i\leq m,m=50000\)

题解

  设\(f_{i,j}\)为以\(i\)为根的子树都赋了值后\(a_i=j\)的方案数。那么怎么处理\(f_v\)对\(f_i\)的贡献呢?

\[g_i=\mu(i)\sum_{i|j}f_{v,j}\\
f_{x,i}\times=\sum_{j|i}g_j
\]

  \(f_{v,i}\)对\(f_{x,j}\)的贡献是\(\sum_{k|(i,j)}\mu(k)f_{v,i}\)。因为\(\sum_{d|n}\mu(d)=[n=1]\),所以只有\(\gcd(i,j)=1\)是\(f_{v,i}\)对\(f_{x,j}\)有贡献。

  设\(h_{i,j}\)为整棵树都赋了值后\(a_i=j\)的方案数。我们发现,\(h_v\)是把\(h_x\)减去\(f_v\)后再加到\(f_v\)上。用逆元搞一搞即可。

  然后就是愉快的卡常时间了。

  时间复杂度:\(O(nm\log m)\)

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<list>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
ll p=1000000007;
int m=50000;
ll fp(ll a,ll b)
{
ll s=1;
while(b)
{
if(b&1)
s=s*a%p;
a=a*a%p;
b>>=1;
}
return s;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b)
{
x=1;
y=0;
return a;
}
ll ab=a/b;
ll c=a-b*ab;
ll d=exgcd(b,c,y,x);
y-=x*ab;
return d;
}
namespace prime
{
int cnt;
int b[100010];
int p[100010];
int u[100010];
void init()
{
cnt=0;
memset(b,0,sizeof b);
int i,j;
u[1]=1;
for(i=2;i<=m;i++)
{
if(!b[i])
{
p[++cnt]=i;
u[i]=-1;
}
for(j=1;j<=cnt&&i*p[j]<=m;j++)
{
b[i*p[j]]=1;
if(i%p[j]==0)
{
u[i*p[j]]=0;
break;
}
u[i*p[j]]=-u[i];
}
}
}
};
list<int> li[60];
int l[60];
int r[60];
ll ans[60];
ll f[60][50010];
ll g[60][50010];
ll c[50010];
ll d[50010];
ll e[50010];
void p0(int x)
{
while(x--)
printf(" 0");
printf("\n");
}
void calc()
{
memset(d,0,sizeof d);
memset(e,0,sizeof e);
int i,j;
for(i=1;i<=m;i++)
if(prime::u[i])
{
for(j=i;j<=m;j+=i)
e[i]+=c[j];
e[i]%=p;
e[i]*=prime::u[i];
}
for(i=1;i<=m;i++)
if(e[i])
for(j=i;j<=m;j+=i)
d[j]+=e[i];
for(i=1;i<=m;i++)
d[i]%=p;
}
void dfs1(int x,int fa)
{
int i;
for(i=l[x];i<=r[x];i++)
f[x][i]=1;
for(auto v:li[x])
if(v!=fa)
{
dfs1(v,x);
memcpy(c,f[v],sizeof f[v]);
calc();
for(i=l[x];i<=r[x];i++)
{
g[v][i]=d[i];
f[x][i]=f[x][i]*d[i]%p;
}
}
}
void dfs2(int x,int fa)
{
int i;
if(fa)
{
// memcpy(c,f[x],sizeof f[x]);
// calc();
ll v1,v2;
for(i=1;i<=m;i++)
// if(f[fa][i]&&d[i])
// {
//// c[i]=f[fa][i]*fp(d[i],p-2)%p;
// int gcd=exgcd(d[i],p,v1,v2);
// if(gcd==-1)
// v1=-v1;
// c[i]=f[fa][i]*v1%p;
// }
if(f[fa][i]&&g[x][i])
{
int gcd=exgcd(g[x][i],p,v1,v2);
if(gcd==-1)
v1=-v1;
c[i]=f[fa][i]*v1%p;
}
else
c[i]=0;
calc();
for(i=l[x];i<=r[x];i++)
f[x][i]=f[x][i]*d[i]%p;
}
for(i=l[x];i<=r[x];i++)
{
f[x][i]=(f[x][i]%p+p)%p;
ans[x]=(ans[x]+f[x][i]*i%p)%p;
}
for(auto v:li[x])
if(v!=fa)
dfs2(v,x);
}
void solve()
{
int n;
scanf("%d",&n);
int i;
for(i=1;i<=n;i++)
scanf("%d",&l[i]);
for(i=1;i<=n;i++)
scanf("%d",&r[i]);
for(i=1;i<=n;i++)
li[i].clear();
int x,y;
for(i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
li[x].push_back(y);
li[y].push_back(x);
}
for(i=1;i<=n;i++)
if(l[i]>r[i])
{
p0(n);
return;
}
memset(g,0,sizeof g);
memset(f,0,sizeof f);
memset(ans,0,sizeof ans);
dfs1(1,0);
dfs2(1,0);
for(i=1;i<=n;i++)
printf("%lld ",ans[i]);
printf("\n");
}
int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
int t;
prime::init();
scanf("%d",&t);
while(t--)
solve();
return 0;
}

【XSY1602】安全网络 树形DP 数学的更多相关文章

  1. 3月28日考试 题解(二分答案+树形DP+数学(高精))

    前言:考试挂了很多分,难受…… --------------------- T1:防御 题意简述:给一条长度为$n$的序列,第$i$个数的值为$a[i]$.现让你将序列分成$m$段,且让和最小的一段尽 ...

  2. Educational Codeforces Round 58 (Rated for Div. 2) D 树形dp + 数学

    https://codeforces.com/contest/1101/problem/D 题意 一颗n个点的树,找出一条gcd>1的最长链,输出长度 题解 容易想到从自底向长转移 因为只需要g ...

  3. [USACO08JAN] 手机网络 - 树形dp

    经典问题系列 覆盖半径\(1\)的最小点覆盖集 \(f[i][0]\) 表示不在此处建信号塔,但\(i\)及其子树都有信号 \(f[i][1]\) 表示在此处建信号塔,但\(i\)及其子树都有信号 \ ...

  4. 树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree

    // 树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree // 题意:n个点的树,每个节点有权值为正,只能用一次,每条边有负权,可以 ...

  5. 【树形dp】Bzoj3391 [Usaco2004 Dec]Tree Cutting网络破坏

    Description     约翰意识到贝茜建设网络花费了他巨额的经费,就把她解雇了.贝茜很愤怒,打算狠狠报 复.她打算破坏刚建成的约翰的网络.    约翰的网络是树形的,连接着N(1≤N≤1000 ...

  6. BZOJ_1495_[NOI2006]网络收费_树形DP

    BZOJ_1495_[NOI2006]网络收费_树形DP Description 网络已经成为当今世界不可或缺的一部分.每天都有数以亿计的人使用网络进行学习.科研.娱乐等活动.然而, 不可忽视的一点就 ...

  7. 5.21 省选模拟赛 luogu P4297 [NOI2006]网络收费 树形dp

    LINK:网络收费 还是自己没脑子. 早上思考的时候 发现树形dp不可做 然后放弃治疗了. 没有合理的转换问题的模型是我整个人最大的败笔. 暴力也值得一提 爆搜之后可以写成FFT的形式的计算贡献的方法 ...

  8. hdu6446 网络赛 Tree and Permutation(树形dp求任意两点距离之和)题解

    题意:有一棵n个点的树,点之间用无向边相连.现把这棵树对应一个序列,这个序列任意两点的距离为这两点在树上的距离,显然,这样的序列有n!个,加入这是第i个序列,那么这个序列所提供的贡献值为:第一个点到其 ...

  9. HDU 6201 2017沈阳网络赛 树形DP或者SPFA最长路

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6201 题意:给出一棵树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过 ...

随机推荐

  1. koa2实现session的两种方式(基于Redis 和MySQL)

    一.基于MySQL的实现方式 这种方式需要安装koa-session-minimal和koa-mysql-session两个依赖. 执行 npm install koa-session-minimal ...

  2. 浅谈一类无关序列有前缀和性质的统计问题的离线解法 BZOJ3626

    每次询问[l,r]区间,但所有信息是按另一种序列给出的,因此无法使用区间数据结构做这种题.将每个询问改为[1,x],考虑离线,则从1~n依次修改并查询即可. BZOJ3626 给定一颗树,每次询问给定 ...

  3. 网络编程-C/S架构

    什么是C/S架构 C指的是client(客户端软件),S指的是Server(服务端软件),本章的重点就是教大家写一个C/S架构的软件,实现服务端软件与客户端软件基于网络通信. 计算机基础知识 作为应用 ...

  4. C. Prefixes and Suffixes

    链接 [https://codeforces.com/contest/1092/problem/C] 题意 给你某个字符串的长度n,再给你2*n-2个前缀或者后缀 让你判断那些是前缀那些是后缀 关键是 ...

  5. ps昏暗室内照片调成暖色光亮效果

    最终效果 一.打开素材图片,把背景图层复制一层,做HDR滤镜操作,如果你没有这款滤镜,可以去网上下载,参数及效果如下图. 二.复制一层,用Noise滤镜做降噪处理,参数及效果如下图. 三.新建一个图层 ...

  6. 分享一个小设置-项目启动时服务器指向本地IIS

    背景,在X公司做的一个网站登录时需要域名的支持,就是说浏览器地址栏在localhost+端口号的形式下无法实现登录(必须是xxxx域名的形式), 但是很多时候都会先在线下进行测试,既然本地没有线上的环 ...

  7. Pair Project

    以前只是一个人完成一个项目,不论什么都是,现在突然要两个人一起来写, 听上去挺稀奇的,也挺简单的,可惜了就是“听上去”而已.我认为这也是一种技术啊~ 我跟我的搭档研究了好久好久,选择了好久,然后也选了 ...

  8. 【学习总结】Git学习-参考廖雪峰老师教程十-自定义Git

    学习总结之Git学习-总 目录: 一.Git简介 二.安装Git 三.创建版本库 四.时光机穿梭 五.远程仓库 六.分支管理 七.标签管理 八.使用GitHub 九.使用码云 十.自定义Git 期末总 ...

  9. 【问题解决方案】之 jmeter启动报错:Not able to find Java executable or version. Please check your Java installation

    故事发生在云计算实验课上-- ** 故事发生在云计算实验课上-- Step 1 在Xshell中登录自己的cloud虚拟机后,<sudo su ->切换到root用户 Step 2 < ...

  10. 硬盘扩容9999T

    win+r运行创建命令:subst H: d:\123说明:H指的是想要创建的盘符,d:\123是文件路径 删除命令subst H: d/说明 :H指的是已创建的盘符,/d指的是删除的意思 注意新盘符 ...