cf330 594D — REQ
2015-11-20 21:39
239 查看
题目描述:
题解:
其实是一道很躶的题目。关键是求出L到R之间的质数的出现情况。想到一种莫队的算法,但是可能会超时。
因此有下面一种很实用的方法。对于离线查询,我们相当于可以固定左端点,那么其实对于质数p,就是从l之后的第一个出现p的位置是关键位置。我们用线段树来区间修改。最开始预处理所有的结果为正确的。然后随着l的平移,对于删掉的左边的数,它的质数应从l到下一个l-1之间都要去除这个质数的影响。搞一搞就行了
重点:
关键是离线相当于可以固定l。 然后我们对于固定的l来说,我们一个p只需要一个关键的位置,就可以描述。学习了金爷两个姿势。
1。搞一个数的质数。
2。vec【i】。back 和 front。
3。另外学一下树状数组把。。。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <algorithm> #define lrt (rt<<1) #define rrt ((rt<<1)|1) #define mid ((l+r)/2) using namespace std; typedef long long ll; const int maxn = 1e6 + 100; const int MAXNODE = maxn; const int M = 1e9 + 7.1; const int MAXVAL = 1e6 + 0.5; struct node { int l, r, id; node(int _l = 0, int _r = 0, int _id = 0) { l = _l; r = _r; id = _id; } }; int n, a[maxn], mul[maxn], tree[maxn], cur[maxn], p[maxn], pn, vis[maxn], qn, rev[maxn], ans[maxn], bo[maxn]; node q[maxn]; vector<int> vec[maxn]; vector<int> num[maxn]; int mult(int a, int b) { int c = (ll)a * (ll)b % M; return c; } int pow_mod(int x, int n) { int res = 1; int tmp = x % M; while(n) { if(n&1) res = mult(res, tmp); tmp = mult(tmp, tmp); n >>= 1; } return res; } int getRev(int x) { return pow_mod(x, M - 2); } void prime() { memset(vis, 0, sizeof(vis)); pn = 0; for(int i = 2; i <= MAXVAL; i++) { if(vis[i] == 0) { p[pn] = i; pn++; vis[i] = 1; bo[i] = i; } for(int j = 0; j < pn && i * p[j] <= MAXVAL; j++) { bo[i * p[j]] = p[j]; vis[i * p[j]] = 1; if(i % p[j] == 0) break; } } } void pushDown(int rt) { if(tree[rt] == 1) return; tree[lrt] = mult(tree[lrt], tree[rt]); tree[rrt] = mult(tree[rrt], tree[rt]); tree[rt] = 1; } void change(int L, int R, int key, int rt, int l, int r) { if(L <= l && R >= r) { tree[rt] = mult(tree[rt], key); return; } pushDown(rt); if(L <= mid) change(L, R, key, lrt, l, mid); if(R >= mid + 1) change(L, R, key, rrt, mid + 1, r); } int query(int pos, int rt, int l, int r) { if(r == l && r == pos) { return tree[rt]; } pushDown(rt); if(pos <= mid) return query(pos, lrt, l, mid); else return query(pos, rrt, mid + 1, r); } void dfs_init(int rt, int l, int r) { if(l == r) { tree[rt] = 1; return; } tree[rt] = 1; dfs_init(lrt, l, mid); dfs_init(rrt, mid + 1, r); } void solve() { for(int i = 0; i <= MAXVAL; i++) vec[i].clear(); mul[0] = 1; for(int i = 1; i <= n; i++) { mul[i] = mult(mul[i-1], a[i]); num[i].clear(); int x = a[i]; while(x != 1) { int t = bo[x]; vec[t].push_back(i); num[i].push_back(t); while(x % t == 0) x /= t; } } dfs_init(1, 1, n); for(int i = 2; i <= MAXVAL; i++) { if(vec[i].size() >= 1) change(vec[i][0], n, (ll)(i-1) * (ll)rev[i] % M, 1, 1, n); cur[i] = 0; } int tl = 1; for(int i = 0; i < qn; i++) { while(tl < q[i].l) { for(int j = 0; j < num[tl].size(); j++) { int x = num[tl][j], tr; if(cur[x] + 1 >= vec[x].size()) { cur[x]++; tr = n+1; } else { tr = vec[x][cur[x] + 1]; cur[x]++; } change(tl + 1, tr - 1, (ll)x * (ll)rev[x-1] % M, 1, 1, n); } tl++; } int res = (ll)mul[q[i].r] * (ll)getRev(mul[q[i].l - 1]) % M * (ll)query(q[i].r, 1, 1, n) % M; ans[q[i].id] = res; } for(int i = 0; i < qn; i++) { printf("%d\n", ans[i]); } } bool cmp(node a, node b) { return a.l < b.l; } int main() { freopen("Din.txt", "r", stdin); prime(); for(int i = 1; i <= MAXVAL; i++) rev[i] = getRev(i); while(scanf("%d", &n) != EOF) { for(int i = 1; i <= n; i++) scanf("%d", &a[i]); scanf("%d", &qn); for(int i = 0; i < qn; i++) { scanf("%d%d", &q[i].l, &q[i].r); q[i].id = i; } sort(q, q + qn, cmp); solve(); } return 0; }
相关文章推荐
- 编译型语言与解释型语言的区别
- 汉诺塔(梵塔)问题
- ios9中使用UIWebView时的一个问题。
- 关于用网线连开发板和电脑网卡问题
- IIS教程:因权限问题被拒绝访问的解决方案
- UIPasteboard的使用
- 动画效果
- 多线程卖火车票
- IIS注册.NET
- openstack HA配置-Mysql
- ASP.NET-MVC4-05-Views
- ios程序的 .pch 文件丢失后
- 求二元一次方程的根(浮点数输出)
- 左侧固定,右侧宽度自适应
- hdoj 数据的交换输出
- Weblogic Security Realm:weblogic安全领域及账号管理实用工具剖析
- 1101. Quick Sort (25)
- 1101. Quick Sort (25)
- vSphere搭建虚拟化集群环境:二 vSphere5.5主要虚拟化产品安装
- 长见错误