【bzoj4026】dC Loves Number Theory 可持久化线段树
题目描述
输入
第一行,两个正整数,N,Q,表示序列的长度和询问的个数。
输出
Q行,对于每个询问输出一个整数。
样例输入
5 10
3 7 10 10 5
3 4
42 44
241 242
14 9
1201 1201
0 6
245 245
7 7
6 1
1203 1203
样例输出
40
240
12
1200
2
240
4
4
1200
4
题解
可持久化线段树(个人觉得不应该叫做主席树,因为本题是区间线段树)
前置技能:HH的项链 强制在线
标准的做法是离线+树状数组,但是由于要在线处理,所以只能尽量使用可持久化数据结构。
我们还是按照那道题的思路,对于每个数,当它出现时就把它上一次出现的位置删除掉。
那么我们就可以使用可持久化区间线段树完成这样类似的操作。
对于每个数a[i],记录一下它上一个出现的位置last,在i对应的线段树中,把last位置的数-1,并把i位置的数+1。
这样在查询区间[l,r]的时候,在r对应的线段树中,查询[l,r]([l,n]同理)这段区间内数的和即为答案。
比较复杂,稍微理解一下~
就当是理解完了
回过头来看这道题,要求区间乘积的欧拉函数。
欧拉函数是什么请自行百度,怎么求请自行找博客。
这里还是简单说一下吧,$\varphi(x)=x\prod\limits_{prime(i)\& i|x}\frac{i-1}i$。
所以说对于这道题可以维护一个前缀乘积,然后只需要求出区间内的质因子即可。
使用类似于HH的项链的方法,对于一个位置i,枚举a[i]的质因子,如果它在之前last位置出现过,则将i位置对应的线段树的last位置的数除以$\frac {i-1}i$;在i位置的数乘以$\frac{i-1}{i}$。
然后使用可持久化线段树维护区间乘积,查询[l,r]时求出r对应的线段树中[l,r]([l,n]同理)的乘积,再乘上$\frac{mul[r]}{mul[l-1]}$(前缀积)即为答案。
需要筛逆元什么的,参见代码。
#include <cstdio>
#include <algorithm>
#define N 100010
#define M 2100000
using namespace std;
typedef long long ll;
const ll mod = 1000777 , k = 1000005;
ll a[N] , prime[M] , cnt , last[M] , ls[N * 80] , rs[N * 80] , tot , root[N] , inv[M] , sum[N * 80] , mul[N];
bool np[M];
void update(ll p , ll v , ll l , ll r , ll x , ll &y)
{
y = ++tot , sum[y] = sum[x] * v % mod;
if(l == r) return;
ll mid = (l + r) >> 1;
if(p <= mid) rs[y] = rs[x] , update(p , v , l , mid , ls[x] , ls[y]);
else ls[y] = ls[x] , update(p , v , mid + 1 , r , rs[x] , rs[y]);
}
ll query(ll p , ll l , ll r , ll x)
{
if(l >= p) return sum[x];
if(r < p) return 1;
ll mid = (l + r) >> 1;
return query(p , l , mid , ls[x]) * query(p , mid + 1 , r , rs[x]) % mod;
}
int main()
{
ll n , m , i , j , x , y;
ll lastans = 0;
scanf("%lld%lld" , &n , &m);
for(i = 2 ; i <= k ; i ++ )
{
if(!np[i]) prime[++cnt] = i;
for(j = 1 ; j <= cnt && i * prime[j] <= k ; j ++ )
{
np[i * prime[j]] = 1;
if(i % prime[j] == 0) break;
}
}
mul[0] = sum[0] = inv[1] = 1;
for(i = 2 ; i < mod ; i ++ ) inv[i] = (mod - mod / i) * inv[mod % i] % mod;
for(i = 1 ; i <= n ; i ++ )
{
scanf("%lld" , &a[i]) , mul[i] = mul[i - 1] * a[i] % mod , root[i] = root[i - 1];
for(j = 1 ; prime[j] * prime[j] <= a[i] ; j ++ )
{
if(a[i] % prime[j] == 0)
{
if(!last[prime[j]]) update(i , (prime[j] - 1) * inv[prime[j]] % mod , 1 , n , root[i] , root[i]);
else update(last[prime[j]] , prime[j] * inv[prime[j] - 1] % mod , 1 , n , root[i] , root[i]) , update(i , (prime[j] - 1) * inv[prime[j]] % mod , 1 , n , root[i] , root[i]);
last[prime[j]] = i;
while(a[i] % prime[j] == 0) a[i] /= prime[j];
}
}
if(a[i] > 1)
{
if(!last[a[i]]) update(i , (a[i] - 1) * inv[a[i]] % mod , 1 , n , root[i] , root[i]);
else update(last[a[i]] , a[i] * inv[a[i] - 1] % mod , 1 , n , root[i] , root[i]) , update(i , (a[i] - 1) * inv[a[i]] % mod , 1 , n , root[i] , root[i]);
last[a[i]] = i;
}
}
while(m -- ) scanf("%lld%lld" , &x , &y) , x ^= lastans , y ^= lastans , printf("%lld\n" , lastans = query(x , 1 , n , root[y]) * mul[y] % mod * inv[mul[x - 1]] % mod);
return 0;
}
【bzoj4026】dC Loves Number Theory 可持久化线段树的更多相关文章
- BZOJ 4026: dC Loves Number Theory 可持久化线段树 + 欧拉函数 + 数学
Code: #include <bits/stdc++.h> #define ll long long #define maxn 50207 #define setIO(s) freope ...
- 【BZOJ4026】dC Loves Number Theory 分解质因数+主席树
[BZOJ4026]dC Loves Number Theory Description dC 在秒了BZOJ 上所有的数论题后,感觉萌萌哒,想出了这么一道水题,来拯救日益枯竭的水题资源. 给 ...
- [BZOJ4026]dC Loves Number Theory 欧拉函数+线段树
链接 题意:给定长度为 \(n\) 的序列 A,每次求区间 \([l,r]\) 的乘积的欧拉函数 题解 考虑离线怎么搞,将询问按右端点排序,然后按顺序扫这个序列 对于每个 \(A_i\) ,枚举它的质 ...
- BZOJ4026: dC Loves Number Theory
Description dC 在秒了BZOJ 上所有的数论题后,感觉萌萌哒,想出了这么一道水题,来拯救日益枯 竭的水题资源. 给定一个长度为 n的正整数序列A,有q次询问,每次询问一段区间内所 ...
- [BZOJ4026]dC Loves Number Theory(线段树)
根据欧拉函数的定义式可知,可以先算出a[l]*a[l+1]*...*a[r]的值,然后枚举所有存在的质因子*(p-1)/p. 发现这里区间中一个质因子只要计算一次,所以指计算“上一个同色点在区间外”的 ...
- [bzoj4026]dC Loves Number Theory_主席树_质因数分解_欧拉函数
dC Loves Number Theory 题目大意:dC 在秒了BZOJ 上所有的数论题后,感觉萌萌哒,想出了这么一道水题,来拯救日益枯竭的水题资源. 给定一个长度为 n的正整数序列A,有q次询问 ...
- POJ 2104 K-th Number (可持久化线段树)
题目大意 给一个长度为n的序列,有m个询问,每次询问一个区间里面第k小的数. 解题分析 静态的区间第k大.复习了一下可持久化线段树. 首先对数值离散化,建一颗权值线段树.按照序列的顺序依次插入,每一个 ...
- bzoj 4026 dC Loves Number Theory 主席树+欧拉函数
题目描述 dC 在秒了BZOJ 上所有的数论题后,感觉萌萌哒,想出了这么一道水题,来拯救日益枯竭的水题资源.给定一个长度为 n的正整数序列A,有q次询问,每次询问一段区间内所有元素乘积的φ(φ(n)代 ...
- bzoj 4026 dC Loves Number Theory
把我写吐了 太弱了 首先按照欧拉函数性质 我只需要统计区间不同质数个数就好了 一眼主席树 其次我被卡了分解质因数这里 可以通过质数筛时就建边解决 不够灵性啊,不知道如何改 #include<bi ...
随机推荐
- 洛谷 P1880 石子合并
题目描述 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1个算法,计算出将N堆石子合并成1 ...
- Intel 快速存储蓝屏
今天电脑蓝屏,DPC Watchdog Violation 很烦.开bluescreen说是NT内核的问题 开windbg说是Intel快速存储的问题,顺手卸载快速存储 卸载前 卸载后 另外我看Int ...
- URAL 2027 URCAPL, Episode 1 (模拟)
题意:给你一个HxW的矩阵,每个点是一个指令,根据指令进行一系列操作. 题解:模拟 #include<cstdio> #include<algorithm> using nam ...
- python_104_面向对象总结
参考(都要认真看看):http://www.cnblogs.com/alex3714/articles/5188179.html http://www.cnblogs.com/alex3714/art ...
- 《队长说得队》【Alpha】Scrum meeting 3
项目 内容 这个作业属于哪个课程 >>2016级计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 >>实验十二 团队作业8:软件测试与ALPHA冲刺 团队名称 ...
- C10 C语言数据结构
目录 枚举 结构体 共用体 枚举 enum enum枚举是 C 语言中的一种基本数据类型,它可以让数据更简洁,更易读. 枚举语法定义格式为: enum 枚举名 {枚举元素1,枚举元素2,……}; 枚举 ...
- 01_1_Struts环境搭建
01_1_Struts环境搭建 1. MyEclipse配置部分 1.1创建项目 新建new—>Project—>Web Project—>Project Name(配置项目名)—& ...
- MFC中获得各种指针概述(个人觉得是很重要的重点)
前言:这学期学习MFC(有点过时的东西),上课时,老师讲到获取当前活动指针,获取视图指针,文档指针,文档模板指针等(已晕) 后来下来真正写代码的时候发现这些几乎都是需要用到的东西,所以特此记录下,让自 ...
- Factorialize a Number-freecodecamp算法题目
Factorialize a Number(计算一个整数的阶乘) 要求 给定一个整数,求其阶乘(用字母n来代表一个整数,阶乘代表着所有小于或等于n的整数的乘积) 思路 确定乘的次数 用for循环进行累 ...
- k8s 基于NFS部署storageclass pv自动供给
在k8s中部署有状态应用时,通常需要做数据持久化存储. 后端存储的方式有以下几种: 1.基于宿主机本地的存储方式: (重启pod时,若pod被调度到其他节点上,尽管原来节点上的数据不会丢失,但是其他节 ...