Codeforce385C 树状数组+素因子分解
2015-09-10 22:26
274 查看
题目大意:
给多个区间的询问,在询问区间内每一个出现的素数去计算所有数中有多少个数能被这个素数整除
然后将所有素数得到的对应值求和
这里因为初始给定的数不超过10000000,最多670000不到的素数
而后面给定的区间到达1e9是没意义的,只要后面超过10000000都按最后一个数表示即可
然后将素数的标号作为树状数组的点,保存对应的点前缀和
给多个区间的询问,在询问区间内每一个出现的素数去计算所有数中有多少个数能被这个素数整除
然后将所有素数得到的对应值求和
这里因为初始给定的数不超过10000000,最多670000不到的素数
而后面给定的区间到达1e9是没意义的,只要后面超过10000000都按最后一个数表示即可
然后将素数的标号作为树状数组的点,保存对应的点前缀和
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <ctime> #include <cstdlib> #include <vector> #include <algorithm> using namespace std; #define ll long long #define N 10001000 #define M 670000 #define pii pair<int,int> #define lowbit(x) x&(-x) int prime[M+5] , tot ; bool check[N+5]; void get_prim() { for(int i=2 ; i<=N ; i++){ if(!check[i]) prime[tot++] = i; for(int j=0 ; j<tot ; j++){ if((ll)i*prime[j]>N) break; check[i*prime[j]] = true; if(i%prime[j]==0) break; } } } int Hash1(int x) { if(x>10000000) return 664580; //664579是10000000内素数的数目 int l=0 , r=tot-1 , ans=0; while(l<=r){ int m = (l+r)>>1; if(prime[m]>=x){ans = m , r=m-1;} else l=m+1; } return ans+1; } int Hash2(int x) { if(x>10000000) return 664580; int l=0 , r=tot-1 , ans=0; while(l<=r){ int m = (l+r)>>1; if(prime[m]<=x){ans = m , l=m+1;} else r=m-1; } return ans+1; } ll sum[M]; void add(int x , int v){for(int i=x ; i<=tot ; i+=lowbit(i)) sum[i] += v;} ll query(int x) { ll ret = 0; for(int i=x ; i>0 ; i-=lowbit(i)) ret+=sum[i]; return ret; } void fenjie(int x) { int mx = (int)sqrt(x+0.5); for(int i=0 ; i<tot ; i++){ if(prime[i]*prime[i]>x) break; if(x%prime[i]==0){ // cout<<"in: "<<i<<" "<<prime[i]<<endl; add(i+1 , 1); while(x%prime[i]==0) x/=prime[i]; } } if(x>1){ int pos = lower_bound(prime , prime+tot , x)-prime; add(pos+1 , 1); } } int main() { // freopen("a.in" , "r" , stdin); // freopen("out.txt" , "w" , stdout); get_prim(); int n , m , s , t; while(~scanf("%d" , &n)) { for(int i=0 ; i<n ; i++){ int x ; scanf("%d" , &x); fenjie(x); } scanf("%d" , &m); while(m--){ scanf("%d%d" , &s , &t); int p1 = Hash1(s) , p2 = Hash2(t); // cout<<p1<<" "<<p2<<endl; printf("%I64d\n" , query(p2)-query(p1-1)); } } }
相关文章推荐
- C++的学习心得
- Linux Tools
- ANGULAR JS WATCH监听使用
- 数据结构之双向循环链表操作4-(插入,删除,建立等)
- 24-ssh启动出现rt.jar:Permission denied
- Android 酷炫来袭:制作属于你自己的音频播放器(综合运用MediaPlayer、Service、Broadcast、ListView、SeekBar)
- ubuntu14.04更新源出错解决
- ubuntu14.04更新源出错解决
- hdu 5288 OO’s Sequence(计数)
- Android学习——其他View
- layout elements
- java之代理
- 数组和面向对象(封装)
- poj 2186 Popular Cows 有向图强连通分量 tarjan
- 正则表达式的学习与小结
- NULL指针、零指针、野指针
- Linux常用命令——搜索which,whereis,slocate,find,grep
- EM算法及其推广的要点
- poj 2186 Popular Cows 有向图强连通分量 tarjan
- 关于JS单选按钮与复选按钮验证是否选中