【NOIP2017提高A组模拟7.13】好数
来源:互联网 发布:不使用域名需要备案吗 编辑:程序博客网 时间:2024/06/05 09:20
题目大意:
我们定义一个非负整数是“好数”,当且仅当它符合以下条件之一:
1.这个数是0或1
2.所有小于这个数且与它互质的正整数可以排成一个等差数列例如,8就是一个好数,因为1,3,5,7排成了等差数列。
给出N个非负整数,然后进行如下三个操作:
1.询问区间[L,R]有多少个好数
2.将区间[L,R]内所有数对S取余(S≤1000000)
3.将第C个数更改为X
题解:
首先我们打个表就可以知道好数只有质数、2的幂、0和6这些数,于是我们一个线性筛法就可以求出所有的好数。
接着我们发现除了2操作,都是一个线段树就可以维护的。
2操作怎么办呢?
对于一个数,如果一直用比它大的数去mod它,最多只会mod log2 次,因为一次最多剩下一半。
因此,我们可以在线段树中记录该区间的最大值,如果这个最大值大于mod数,就往下递归,把所有的大于mod数的数mod一遍。
还有单点修改操作,这个操作最多就把一个数拔高一下,重回log次。
所以总共的时间是
Code:
#include <cstdio>#include <cstring>#define fo(i, x, y) for(int i = x; i <= y; i ++)#define max(a, b) ((a) > (b) ? (a) : (b))using namespace std;const int N = 1000005;bool bz[N]; int p[N];int n, m, num, l, r, s, a[100005];struct node { int s, m;}t[N * 10];void update(int i) { t[i].m = max(t[i + i].m, t[i + i + 1].m); t[i].s = t[i + i].s + t[i + i + 1].s;}void insert(int i, int x, int y, int l, int r) { if(x == y) { a[x] = r; t[i].s = !bz[r]; t[i].m = r; return; } int m = (x + y) / 2; if(l <= m) insert(i + i, x, m, l, r); else insert(i + i + 1, m + 1, y, l, r); update(i);}void change(int i, int x, int y, int l, int r, int mo) { if(t[i].m < mo) return; if(x == y) { a[x] %= mo; t[i].s = !bz[a[x]]; t[i].m = a[x]; return; } int m = (x + y) / 2; if(r <= m) change(i + i, x, m, l, r, mo); else if(l > m) change(i + i + 1, m + 1, y, l, r, mo); else change(i + i, x, m, l, m, mo), change(i + i + 1, m + 1, y, m + 1, r, mo); update(i);}int find(int i, int x, int y, int l, int r) { if(x == l && y == r) return t[i].s; int m = (x + y) / 2; if(r <= m) return find(i + i, x, m, l, r); else if(l > m) return find(i + i + 1, m + 1, y, l, r); return find(i + i, x, m, l, m) + find(i + i + 1, m + 1, y, m + 1, r);}int main() { fo(i, 2, 1e6) { if(!bz[i]) p[++ p[0]] = i; fo(j, 1, p[0]) { if(i * p[j] > N) break; bz[i * p[j]] = 1; if(i % p[j] == 0) break; } } bz[0] = bz[6] = 0; int s = 1; while(s <= 1e6) { bz[s] = 0; s *= 2; } scanf("%d %d", &n, &m); fo(i, 1, n) scanf("%d", &a[i]), insert(1, 1, n, i, a[i]); fo(i, 1, m) { scanf("%d", &num); if(num == 1) { scanf("%d %d", &l, &r); printf("%d\n", find(1, 1, n, l, r)); } if(num == 2) { scanf("%d %d %d", &l, &r, &s); change(1, 1, n, l, r, s); } if(num == 3) { scanf("%d %d", &l, &r); insert(1, 1, n, l, r); } }}
阅读全文
1 0
- JZOJ 100045. 【NOIP2017提高A组模拟7.13】好数
- 【NOIP2017提高A组模拟7.13】好数
- JZOJ100045. 【NOIP2017提高A组模拟7.13】好数
- 【NOIP2017提高A组模拟7.13】abcd
- 【NOIP2017提高A组模拟7.13】第K小数
- JZOJ100043. 【NOIP2017提高A组模拟7.13】第K小数
- A【NOIP2017提高组模拟12.18】
- 【JZOJ4928】【NOIP2017提高组模拟12.18】A
- 【NOIP2017提高组模拟12.18】A
- 【JZOJ4928】【NOIP2017提高组模拟12.18】A
- 【NOIP2017提高A组模拟7.7】图
- 区间【NOIP2017提高A组模拟7.10】
- 【NOIP2017提高A组模拟8.22】密码
- 【NOIP2017提高A组模拟8.23】密码
- 【NOIP2017提高A组模拟8.24】早苗
- 【NOIP2017提高A组模拟8.24】提米树
- 空【NOIP2017提高A组模拟8.24】
- 【NOIP2017提高A组模拟8.25】影子
- Linux 的多线程编程的高效开发经验
- linux常见命令用法
- 使用Mysql中group_concat函数中的陷阱
- flask+Gunicorn+Nginx安装与配置
- Maven学习笔记(一)--用途、下载、安装
- 【NOIP2017提高A组模拟7.13】好数
- this指针的原理
- [bzoj4545] DQS的trie
- json解析时自动判断是object还是array
- jmeter与session(3)
- [java泛型] 泛型的继承规则
- cdev_alloc和cdev_init 的使用
- opencv初级学习之图像显示
- android BroadcastReceiver(广播)