牛客练习赛9 F - 珂朵莉的约数
题目描述
珂朵莉给你一个长为n的序列,有m次查询
每次查询给两个数l,r
设s为区间[l,r]内所有数的乘积
求s的约数个数mod 1000000007
输入描述:
第一行两个正整数n,m
第二行一个长为n的序列
之后m行每行两个数l和r
输出描述:
对于每个询问,输出一个整数表示答案
输入
5 5
64 2 18 9 100
1 5
2 4
2 3
1 4
3 4
输出
165
15
9
45
10
备注:
对于100%的数据,有n , m <= 100000 , a[i] <= 1000000
题解
莫队算法,质因数分解。
本质就是求区间内每个素因子出现的次数的乘积,可以用莫队来搞。
然后超时了......分析了一波发现每个数最多可以分解成$20$个左右的素因子,也就是莫队增加一个数删除一个数的时候,需要进行$20$个数的修改。
常数有点大。又分析了一波,发现每个数最多只能分解成$7$个素因子,也就是按种类来修改可以减少一些常数。还是超时......
最后看了题解,发现好强啊......:
对每个数进行质因子分解,考虑一个数的约数个数即为其每个质因子出现次数+1的乘积,所以维护这个即可
考虑每个数只有一个大于1000的质数,对这部分进行根号分治
对于小于1000的质因子(只有168个),维护一个前缀和pre[i][j]表示第i个质因子在前j个数中出现次数
对于大于1000的质因子,用莫队维护即可
这样操作,莫队转移复杂度大大降低,小的素因子一波搞就$ok$了。
然后写莫队的时候发现了曾经没有注意到的事情,就是要先进行$add$,然后进行$delete$。不举例了。
#include <bits/stdc++.h>
using namespace std; const int maxn = 1e5 + 10;
const long long mod = 1000000007LL;
int a[maxn];
int b[maxn];
int sum[maxn][200];
int c[50], g;
int cnt[10 * maxn]; int pos[maxn];
int n, m, L, R;
long long Ans; struct X {
int l, r, id;
}s[maxn];
long long ans[maxn]; bool cmp(const X& a, const X& b) {
if (pos[a.l] != pos[b.l]) return a.l < b.l;
if((pos[a.l]) & 1) return a.r > b.r;
return a.r < b.r;
} bool noprime[10 * maxn];
int prime[10 * maxn], num_prime;
long long inv[20 * maxn]; void init() {
inv[0] = inv[1] = 1;
for(long long i = 2; i <= 2000005; i ++) {
inv[i] = inv[mod % i] * (mod - mod / i) % mod;
}
noprime[1] = 1;
for(int i = 2; i <= 1000000; i ++) {
if(noprime[i]) continue;
prime[num_prime ++] = i;
for(int j = i + i ; j <= 1000000; j = j + i) {
noprime[j] = 1;
}
}
} void add(int x) {
if(x == 0) return;
Ans = Ans * inv[cnt[x] + 1] % mod;
cnt[x] += 1;
Ans = Ans * (cnt[x] + 1) % mod;
} void del(int x) {
if(x == 0) return;
Ans = Ans * inv[cnt[x] + 1] % mod;
cnt[x] -= 1;
Ans = Ans * (cnt[x] + 1) % mod;
} int main() {
init();
scanf("%d%d", &n, &m);
int sz = sqrt(n);
for(int i = 1; i <= n; i ++) {
scanf("%d", &a[i]);
pos[i] = i / sz;
int now = 0;
int tmp = a[i];
g = 0;
while(tmp != 1) {
if(noprime[tmp] == 0) {
c[g ++] = tmp;
tmp = 1;
} else {
while(tmp % prime[now] == 0) {
c[g ++] = prime[now];
tmp = tmp / prime[now];
}
now ++;
}
}
for(int j = 0; j < g; j ++) {
if(c[j] > 1000) {
b[i] = c[j];
} else {
for(int k = 0; k < 200; k ++) {
if(prime[k] == c[j]) {
sum[i][k] ++;
}
}
}
}
} for(int i = 1; i <= n; i ++) {
for(int j = 0; j < 200; j ++) {
sum[i][j] = sum[i][j] + sum[i - 1][j];
}
} for(int i = 1; i <= m; i ++) {
scanf("%d%d", &s[i].l, &s[i].r);
s[i].id = i;
}
sort(s + 1, s + m + 1, cmp); Ans = 1LL;
for(int i = s[1].l; i <= s[1].r; i ++) {
add(b[i]);
}
for(int j = 0; j < 200; j ++) {
Ans = Ans * (sum[s[1].r][j] - sum[s[1].l - 1][j] + 1) % mod;
} ans[s[1].id] = Ans;
L = s[1].l;
R = s[1].r;
for(int i = 2; i <= m; i ++) {
while (L > s[i].l) { L--, add(b[L]); }
while (R < s[i].r) { R++, add(b[R]); }
while (L < s[i].l) { del(b[L]), L++; }
while (R > s[i].r) { del(b[R]), R--; } for(int j = 0; j < 200; j ++) {
Ans = Ans * inv[sum[s[i - 1].r][j] - sum[s[i - 1].l - 1][j] + 1] % mod;
Ans = Ans * (sum[s[i].r][j] - sum[s[i].l - 1][j] + 1) % mod;
} ans[s[i].id] = Ans;
}
for(int i = 1; i <= m; i ++) {
printf("%lld\n", ans[i]);
}
return 0;
}
牛客练习赛9 F - 珂朵莉的约数的更多相关文章
- 牛客练习赛7 E 珂朵莉的数列
珂朵莉的数列 思路: 树状数组+高精度 离散化不知道哪里写错了,一直wa,最后用二分写的离散化 哪位路过大神可以帮我看看原来的那个离散化错在哪里啊 通过代码: import java.math.Big ...
- 牛客练习赛9 B - 珂朵莉的值域连续段
题目描述 珂朵莉给你一个有根树,求有多少个子树满足其内部节点编号在值域上连续 一些数在值域上连续的意思即其在值域上构成一个连续的区间 输入描述: 第一行有一个整数n,表示树的节点数.接下来n–1行,每 ...
- 牛客练习赛7 E 珂朵莉的数列(树状数组+爆long long解决方法)
https://www.nowcoder.com/acm/contest/38/E 题意: 思路: 树状数组维护.从大佬那里学习了如何处理爆long long的方法. #include<iost ...
- 牛客网 牛客练习赛7 D. 珂朵莉的无向图(多源BFS)
题目链接 Problem D 比赛的时候完全想不到 直接对给定的这些点做多源$BFS$,把给定的这些点全都压到队列里,然后一个个做. 最后统计被访问的点的个数即可. #include <bit ...
- 牛客 40F 珂朵莉的约数 (莫队)
珂朵莉给你一个长为n的序列,有m次查询 每次查询给两个数l,r 设s为区间[l,r]内所有数的乘积 求s的约数个数mod 1000000007 直接莫队暴力维护复杂度是$O(8m\sqrt{m})$. ...
- 牛客练习赛3 F - 监视任务
链接:https://www.nowcoder.net/acm/contest/13/F来源:牛客网 题目描述
- 牛客网 牛客练习赛43 F.Tachibana Kanade Loves Game-容斥(二进制枚举)+读入挂
链接:https://ac.nowcoder.com/acm/contest/548/F来源:牛客网 Tachibana Kanade Loves Game 时间限制:C/C++ 1秒,其他语言2秒 ...
- 牛客练习赛16 F 选值【二分/计数】
链接:https://www.nowcoder.com/acm/contest/84/F 来源:牛客网 题目描述 给定n个数,从中选出三个数,使得最大的那个减最小的那个的值小于等于d,问有多少种选法. ...
- 牛客练习赛29 F 算式子
https://www.nowcoder.com/acm/contest/211/F 经典题. 1.分区间 2.向下取整的值变化 & 合并相同值 #include <bits/stdc+ ...
随机推荐
- novaclient源码分析
源码版本:H版 FAULT_OS_COMPUTE_API_VERSION = "1.1" 一.目录结构及概况 novaclient/ |---client.py --------- ...
- 阿里云ECS/Ubuntu下***浅析
公司项目中需要WebRTC作为即时通讯部分的核心技术,这部分的开发由我负责.实际上手前需要访问谷歌进行源码的下载以及编译,在这里记录下我各种折腾服务器***过程. 目前手上有两台阿里云ESC: 华南节 ...
- 782C. Andryusha and Colored Balloons DFS
Link 题意: 给出一棵树,要求为其染色,并且使任意节点都不与距离2以下的节点颜色相同 思路: 直接DFS.由某节点出发的DFS序列,对于其个儿子的cnt数+1,那么因为DFS遍历的性质可保证兄弟结 ...
- 利用ChainMap进行多字典合并
aa = [{105199: 'https://picx0.jpeg'}, {105187: 'https://picx1.jpeg'}, {105170: 'https:picx2.jpeg'}, ...
- nginx目录路径重定向[转]
如果希望域名后边跟随的路径指向本地磁盘的其他目录,而不是默认的web目录时,需要设置nginx目录访问重定向. 应用场景:dashidan.com/image自动跳转到dashidan.com/fol ...
- 在JavaScript中重写jQuery对象的方法
jQuery是一个很好的类库,它给我们解决了很多的客户端编程,任何东西都不是万能的,当它不能满足我们的需求时我们需要对它进行重写,同时也不要影响其原有的功能或者修改其原有的功能:我现在的web应用程序 ...
- HTML DOM 节点介绍(nodeName,nodeValue,nodeType)
对于初学者来说,HTML DOM 里面的 nodeName.nodeValue 以及 nodeType 三个属性的作用和取值不是很清楚.下面整理的信息包含有关于节点的详细信息,供参考. 节点信息 每个 ...
- 【BZOJ】2820: YY的GCD
[题意]给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对.T<=10^4,N,M<=10^7. [算法]数论(莫比乌 ...
- JavaScript计时器
计时器 基本格式: setInterval(function(){代码},1000): /* 说明:1.setInterval 会返回一个计时器ID值 可以这样接收.var setId = setIn ...
- NYOJ 2 括号配对问题 (模拟)
题目链接 描述 现在,有一行括号序列,请你检查这行括号是否配对. 输入 第一行输入一个数N(0<N<=100),表示有N组测试数据.后面的N行输入多组输入数据,每组输入数据都是一个字符串S ...