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\)(待确定 ...
随机推荐
- java求两个圆相交坐标
最近由于项目需要,根据两个圆函数求出相交的坐标.实现代码如下,另感谢两圆求交点算法实现Java代码,虽然他所贡献的代码中存在问题,但仍有借鉴意义. 1.两个圆相交的数学求法 在中学数学中我们知道,一个 ...
- Python与mongo交互
# 导入模块 import pymongo # 连接MongoDB数据库 conn = pymongo.MongoClient('localhost', 27017) # 建库 db = conn.g ...
- 01 语言基础+高级:1-9 网络编程_day11【网络编程】
day11[网络编程] 主要内容 软件架构CS/BS 网络通信三要素 TCP通信 Socket套接字 ServerSocket 教学目标 能够辨别UDP和TCP协议特点 能够说出TCP协议下两个常用类 ...
- python基础,if判断
一.计算机基础知识: 1.计算机基本组成:主板+CPU+内存 (CPU:主频,核数(16) 内存:大小,型号,主频 显卡:显存,位宽) 2.计算机最低层:电子电路,只能识别0和1. 二.pyt ...
- dubbo配置文件加载顺序
JVM 启动 -D 参数优先,这样可以使用户在部署和启动时进行参数重写,比如在启动时需改变协议的端口. XML 次之,如果在 XML 中有配置,则 dubbo.properties 中的相应配置项无效 ...
- 对《The future of ReactiveCocoa》的一些思考
前言 我以为 第一次接触 swift 语言时,看到函数的表示形式如下: func fun(num: Int) -> Int { return num + 1 } let f = fun(1) 和 ...
- linux mint使用中的问题解决记录
软件升级失败 换用命令行 sudo apt update sudo apt list --upgradable sudo apt upgrade sudo apt autoremove Enter p ...
- You are attempting to install the android sdk inside your android studio installation
原因 我的android studio文件名为AndroidStudio 我的android studio sdk文件名为AndroidStudioSDK 所以系统把AndroidStudioSDK自 ...
- 14 微服务电商【黑马乐优商城】:day06-了解vue-router和webpack的使用
本项目的笔记和资料的Download,请点击这一句话自行获取. day01-springboot(理论篇) :day01-springboot(实践篇) day02-springcloud(理论篇一) ...
- shell里脚本里写个简单的函数,显示颜色
如果多次用到颜色显示,还是定义一个函数比较实在,具体什么颜色上网找一下 #!/bin/bash # 定义一个红色显示的函数 function echo_red () { local what=$* e ...