UVa 11610 Reverse Prime(树状数组+二分)
来源:互联网 发布:Mac 变速播放器 编辑:程序博客网 时间:2024/06/10 21:22
有一些7位数,倒转过之后都是小于10^6的素数,叫做倒素数。把这些倒素数按大小排列,分别求出每个倒素数的素因子个数(比如24是2,2,2,3,共4个);
先有两种操作:
1.q i:查询从第0个到第i个倒素数的所有素因子之和;
2.d x:从这些倒素数中删除x,剩下的倒素数按大小重新排列。
首先把每个倒素数除以10,然后因子个数都先加上2,消除末尾0(题目也是有点无聊);
delete操作add函数可以完成;
主要是删除之后剩下的数重新排列有点麻烦,但是不是不可解决:
1.建立一个维护名次的树状数组,sum(x)就是x的名次,所以初始化的之和每个点都直接更新1,删除的时候直接更新-1;
2.询问真的名次时,则需要二分查找出初始名次,sum函数求出来的数组必然有序,所以需要一个类似于upper_bound的函数(同一值的点必然最后一个是合法的)。
要实现lower_bound和upper_bound的功能只差在等号加在哪个if上。
#include <algorithm>#include <stdlib.h>#include <iostream>#include <string.h>#include <stdio.h>#include <math.h>using namespace std;#define MAXN 670000#define lowbit(x) (x & -x)#define bin(x) (lower_bound(rev, rev + tot, x) - rev)/*.............................................PRIME SIEVE.............................................*/const int maxn = 1000100;const int prin = 300000;int prime[prin];///仅包含奇数,isprime[k]代表2*k+3bool isprime[maxn>>1];int ptop = 0;void sieve(){ memset(isprime, true, sizeof(isprime)); prime[0] = 2; int sq = sqrt(maxn); for(int i = 3; i < maxn; i += 2) { if(isprime[(i-3)>>1]) { if(i <= sq+3) { for(int j = i*i; j < maxn; j += 2*i) { isprime[(j-3)>>1] = false; } } prime[++ptop] = i; } } return ;}/*.............................................PRIME SIEVE.............................................*/int rev[MAXN], fac[MAXN], ss[MAXN], in[MAXN];int tot;int sum(int a[], int i){ int ret = 0; while(i > 0) ret += a[i], i -= lowbit(i); return ret;}int add(int a[], int i, int val){ while(i <= tot) a[i] += val, i += lowbit(i);}int get_rev(int x){ int ret = 0; for(int i = 0; i < 6; i++) ret *= 10, ret += x % 10, x /= 10; return ret;}void init(){ sieve(); for(tot = 0; prime[tot] < 1000000; tot++) rev[tot] = get_rev(prime[tot]); sort(rev, rev + tot); for(int i = 0; i < tot; i++) { fac[i] = 2; //已去掉末尾0 int tmp = rev[i]; for(int j = 0; prime[j] <= sqrt(tmp + 10); j++) while(tmp % prime[j] == 0) tmp /= prime[j], fac[i]++; if(tmp > 1) fac[i]++; } for(int i = 0; i < tot; i++) add(ss, i + 1, fac[i]), add(in, i + 1, 1);}int find(int x, int l = 1, int r = tot + 1){ if(l >= r) return r; int m = (l + r) >> 1; if(sum(in, m) > x) return find(x, l, m); if(sum(in, m) <= x) return find(x, m + 1, r);}char op[4];int x;int main(){// freopen("D.in", "r", stdin);// freopen("D.out", "w", stdout); init(); while(~scanf("%s%d", op, &x)) { if(op[0] == 'q') { int id = find(x + 1) - 1; printf("%d\n", sum(ss, id)); } if(op[0] == 'd') { x /= 10; int id = bin(x); add(ss, id + 1, -fac[id]); add(in, id + 1, -1); } } return 0;}
0 0
- UVa 11610 Reverse Prime(树状数组+二分)
- UVA 11610 Reverse Prime(数论+树状数组+二分)
- UVA - 11610 Reverse Prime
- UVa 11525 Permutation(二分+树状数组)
- uva 11525排列(树状数组 + 二分)
- UVA 11525 - Permutation(二分+树状数组)
- UVA 501 - Black Box(二分 + 树状数组 + 离散化)
- HDU3792---Twin Prime Conjecture(树状数组)
- 1017(二分+树状数组)
- UVA 12086 (树状数组)
- UVA 1513(树状数组)
- uva 1644 Prime Gap 二分
- HDU 4339 Query(树状数组+二分)
- codeforces 191 E (树状数组+二分)
- hdu(4339)树状数组+二分查找
- Lost Cows(树状数组+二分)
- hdu 2852(树状数组+二分)
- POJ-2892(树状数组 + 二分)
- hadoop HDFS文件系统的特征
- HDU1867 A + B for you again KMP应用
- Hive "行转列"和"列转行"
- mabatis入门
- 关于为何子类的构造器必须调用父类的构造器一次的解答
- UVa 11610 Reverse Prime(树状数组+二分)
- TIME_WAIT状态详解
- XML配置
- 在windos平台下搭建Cygwin下载安卓源码5.0.2_r1
- js 与或运算符 || && 妙用
- CentOS下JDK和resin安装配置
- PowerEdge R720产品支持操作系统
- Java内部类的使用小结
- Java Web 学习报告(2015年寒假)