2017 ACM-ICPC, Universidad Nacional de Colombia Programming Contest K - Random Numbers (dfs序 线段树+数论)
Tamref love random numbers, but he hates recurrent relations, Tamref thinks that mainstream random generators like the linear congruent generator suck. That's why he decided to invent his own random generator.
As any reasonable competitive programmer, he loves trees. His generator starts with a tree with numbers on each node. To compute a new random number, he picks a rooted subtree and multiply the values of each node on the subtree. He also needs to compute the number of divisors of the generated number (because of cryptographical applications).
In order to modify the tree (and hence create different numbers on the future), Tamref decided to perform another query: pick a node, and multiply its value by a given number.
Given a initial tree T, where Tu corresponds to the value on the node u, the operations can be summarized as follows:
- RAND: Given a node u compute
and count its divisors, where T(u) is the set of nodes that belong to the subtree rooted at u.
- SEED: Given a node u and a number x, multiply Tu by x.
Tamref is quite busy trying to prove that his method indeed gives integers uniformly distributed, in the meantime, he wants to test his method with a set of queries, and check which numbers are generated. He wants you to write a program that given the tree, and some queries, prints the generated numbers and count its divisors.
Tamref has told you that the largest prime factor of both Tu and x is at most the Tamref's favourite prime: 13. He also told you that the root of T is always node 0.
The figure shows the sample test case. The numbers inside the squares are the values on each node of the tree. The subtree rooted at node 1 is colored. The RAND query for the subtree rooted at node 1 would generate 14400, which has 63 divisors.
Input
The first line is an integer n (1 ≤ n ≤ 105), the number of nodes in the tree T. Then there are n - 1 lines, each line contains two integers u and v (0 ≤ u, v < n) separated by a single space, it represents that u is a parent of v in T. The next line contains n integers, where the i - th integer corresponds to Ti (1 ≤ Ti ≤ 109). The next line contains a number Q (1 ≤ Q ≤ 105), the number of queries. The final Q lines contain a query per line, in the form "RAND u" or "SEED u x" (0 ≤ u < n, 1 ≤ x ≤ 109).
Output
For each RAND query, print one line with the generated number and its number of divisors separated by a space. As this number can be very long, the generated number and its divisors must be printed modulo 109 + 7.
Example
8
0 1
0 2
1 3
2 4
2 5
3 6
3 7
7 3 10 8 12 14 40 15
3
RAND 1
SEED 1 13
RAND 1
14400 63
187200 126 题意:给一颗树共n个点,以及其结点的数值ai,有q次行为,查询询问子树(包括节点)的数值的积,与更新单个节点即乘题给数(一开始以为是整个子树都要更新) 思路:明显的线段树题,但是问题是线段树里存的是什么。如果直接存积,数组开long long也存不下。那么就需要换种思路,存积的质因子的指数。 即把积X=(p1^a)*(p2^b)*(p3^c)*······中的a,b,c用数组记录。又题目给出子树结点的积可以用不超过13的素数的积来表示。则定义一个b[]={2,3,5,7,11,13}。 就能表示所有子树积。这样查询到以后可以直接用快速幂求得第一问,用乘法原理因子数=(a+1)*(b+1)······即得第二问。 想到这里剩下的操作就是套+改线段树dfs序板子了(这里膜一下月老tql)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<cmath>
#include<set>
#define lid id<<1
#define rid id<<1|1
#define INF 0x3f3f3f3f
#define LL long long
#define debug(x) cout << "[" << x << "]" << endl
using namespace std;
const int maxn = 1e5+;
int b[]={,,,,,};
int d[maxn][]={};
void cal(int x, int *d)
{
for(int i = ;i < ;i++){
while(x%b[i]==)x/=b[i],d[i]++;
}
}
const int mx = 1e5+;
const int mod = 1e9+;
int L[mx], R[mx], p[mx];
struct tree{
int l, r;
int p[]; //2,3,5,7,11,13
int lazy[];
}tree[mx<<];
vector<int> G[mx];
int cnt;
LL Ans[] = {}; LL qpow(LL x, LL n){ //x^n
LL res = ;
while (n > ){
if (n & ) res = res*x%mod;
x = x*x % mod;
n >>= ;
}
return res;
} void push_up(int id){
for (int i = ; i < ; i++)
tree[id].p[i] = tree[lid].p[i]+tree[rid].p[i];
} void build(int l, int r, int id){
tree[id].l = l;
tree[id].r = r;
for (int i = ; i < ; i++) tree[id].p[i] = ;
if (l == r) return;
int mid = (l+r) >> ;
build(l, mid, lid);
build(mid+, r, rid);
} void dfs(int u){
L[u] = ++cnt;
int len = G[u].size();
for (int i = ; i < len; i++){
int v = G[u][i];
dfs(v);
}
R[u] = cnt;
} void upd(int c, int id, int *x){
if (tree[id].l == c && tree[id].r == c){
for (int i = ; i < ; i++)
tree[id].p[i] += x[i];
return;
}
int mid = (tree[id].l + tree[id].r)>>;
if (c <= mid) upd(c, lid, x);
else upd(c, rid, x);
push_up(id);
} void query(int l, int r, int id){
if (tree[id].l == l && tree[id].r == r){
for (int i = ; i < ; i++)
Ans[i] += tree[id].p[i];
return;
}
int mid = (tree[id].l + tree[id].r)>>;
if (r <= mid) query(l, r, lid);
else if (mid < l) query(l, r, rid);
else {
query(l, mid, lid);
query(mid+, r, rid);
}
} int main(){
int n, u, v, a, q;
cnt = ;
scanf("%d", &n);
for (int i = ; i < n; i++){
scanf("%d%d", &u, &v);
G[u].push_back(v);
p[v] = u;
}
for (int i = ; i < n; i++){
if (!p[i]) {
dfs(i);
break;
}
}
build(, n, );
for (int i = ; i < n; i++){
scanf("%d", &a);
cal(a,d[i]);
upd(L[i], , d[i]);
}
scanf("%d", &q);
while (q--){
char s[];
int d2[] = {};
scanf("%s%d", s, &a);
if (s[] =='R'){
memset(Ans, , sizeof Ans);
query(L[a], R[a], );
LL ans = ;
LL num = ;
for (int i = ; i < ; i++){
num = (num*qpow(b[i], Ans[i]))%mod;
ans = ans*(Ans[i]+)%mod;
}
printf("%lld %lld\n", num, ans);
}
else {
int c;
scanf("%d", &c);
cal(c, d2);
upd(L[a], , d2);
}
}
return ;
}
2017 ACM-ICPC, Universidad Nacional de Colombia Programming Contest K - Random Numbers (dfs序 线段树+数论)的更多相关文章
- 2020 ICPC Universidad Nacional de Colombia Programming Contest
2020 ICPC Universidad Nacional de Colombia Programming Contest A. Approach 三分 显然答案可以三分,注意\(eps\)还有两条 ...
- 2019 ICPC Universidad Nacional de Colombia Programming Contest C D J
C. Common Subsequence 题意:给出长度为n两个串,求两个串的最长公共子序列len,如果len>=0.99*n,两个串就是亲兄弟否则不是. 解法:朴素的求LCS的时间复杂度是O ...
- 2016 ACM/ICPC Asia Regional Dalian Online HDU 5877 Weak Pair treap + dfs序
Weak Pair Problem Description You are given a rooted tree of N nodes, labeled from 1 to N. To the ...
- 2017 Wuhan University Programming Contest (Online Round) D. Events,线段树区间更新+最值查询!
D. Events 线段树区间更新查询区间历史最小值,看似很简单的题意写了两天才写出来. 题意:n个数,Q次操作,每次操作对一个区间[l,r]的数同时加上C,然后输出这段区间的历史最小值. 思路:在线 ...
- ACM/ICPC 2018亚洲区预选赛北京赛站网络赛 D 80 Days (线段树查询最小值)
题目4 : 80 Days 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 80 Days is an interesting game based on Jules Ve ...
- 2016-2017 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2016) F dfs序+树状数组
Performance ReviewEmployee performance reviews are a necessary evil in any company. In a performance ...
- The 2019 Asia Nanchang First Round Online Programming Contest C(cf原题,线段树维护矩阵)
题:https://nanti.jisuanke.com/t/41350 分析:先将字符串转置过来 状态转移,因为只有5个状态,所以 i 状态到 j 状态的最小代价就枚举[i][k]->[k][ ...
- 2017 ACM/ICPC Asia Regional Shenyang Online spfa+最长路
transaction transaction transaction Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 132768/1 ...
- 2017 ACM ICPC Asia Regional - Daejeon
2017 ACM ICPC Asia Regional - Daejeon Problem A Broadcast Stations 题目描述:给出一棵树,每一个点有一个辐射距离\(p_i\)(待确定 ...
随机推荐
- git常用操作及其基本命令
克隆远程仓库代码到本地 本地创建有文件夹 git clone 远程仓库地址 本地文件夹名称 本地没有创建文件夹 git clone 远程仓库地址 文件夹名称 克隆完成之后,使用“cd 文件夹”的方式进 ...
- 第3章 ZooKeeper基本数据模型
第3章 ZooKeeper基本数据模型 3-1 zk数据模型介绍 3-2 zk客户端连接关闭服务端,查看znode ./zkCli.sh Ctrl + C 退出 =================== ...
- JIT Debug Info 简介
原总结debug调试dump转储文件JITprocdumpJIT Debugging 前言 在上一篇介绍 JIT Debugging 的文章 -- 你需要了解的JIT Debugging 中,我们了解 ...
- usert
usert类型 不是一个函数,而是一个语言构造器 usert后会不会释放内存 当usert的文件大于2044KB时才会释放内存,否则不释放内存
- 使用Anaconda安装TensorFlow
conda create -n tensorflow python=2.7 # or python=3.3, etc. pip install --ignore-installed --upgrade ...
- DOCKER 学习笔记2 认识dockerfile自定义镜像
Dockerfile 概念 Dockerfile 是一个文本文件,但包含所构建容器在运行时候的参数.库.资源配置.可以简单理解为我们现有的镜像,比如Centos/Nginx 但我们需要构建一个容器的时 ...
- Python笔记_第一篇_面向过程_第一部分_5.Python数据类型之元组类型(tuple)
元组!在Python中元组是属于列表的一种延伸,也是一种有序集合,成为一种只读列表,即数据可以被查找,不能被修改,列表的切片操作同样适用于元组. 特点:1. 与列表非常相似. 2. 一旦初始化就不能修 ...
- Docker添加root用户
0 环境 系统环境:centos7 服务器:阿里云 1 正文 1 进入rabbitmq容器中 docker exec -i -t 563 bin/bash 2 添加用户(用户名和密码) rabbitm ...
- Debian8.8为普通用户添加sudo权限
1.进入root用户,su root 输入密码,我们首先修改 /etc/sudoers 文件的属性为可写权限# chmod +w /etc/sudoers2.编辑 vim /etc/sudoers,添 ...
- Matlab高级教程_第二篇:Matlab相见恨晚的模块_02_并行运算-2
1 MATLAB并行计算-从个人桌面到远程集群和云(陈伟/魏奋)视频摘录笔记 https://cn.mathworks.com/videos/parallel-computing-with-matla ...