在那楼梯那边数实里面,有一只 guard,他活泼又聪明,他卖萌又霸气。他每天刷题虐 场 D 人考上了 PKU,如果无聊就去数一数质数~~ 有一天 guard 在纸上写下了一串数字,他发现数出每个数有多少个质因子是非常有(wu) 趣(liao)的事情,于是快乐的开始了数质因子之旅。现在他有一个更有(wu)趣(liao)的想法, 他想知道第a个数到第b个数每个数的质因子个数之和。更有趣的是,他一共写下了200 万个数字哟。由于guard是神犇所以不屑于求如此简单的问题,现在他把问题交给了Mr.shu, 但是他不会…,如果你能回答他的问题就能获得 guard 的亲笔签名哦~~。
第一行 1 个数 n,表示 guard 写下了 n 个数。 第二行 n 个用空格隔开的数,表示 guard 写下的 n 个数(每个数都不大于 10000,不小 于 1)。 第三行 1 个数 m,表示 guard 的询问数。 接下来 m 行,每行一个 a 和 b,表示 guard 想知道 a 到 b(包括 a 和 b)的每个数的质 因子个数之和。
一共 m 行。每行一个数表示对每个询问的答案。
5 4 2 1 6 30 2 1 3 2 5
3 6
【输入输出样例说明】
4=2*2 有 2 个不同质因子,2 有 1 个,1 有 0 个,6 有 2 个,30 有 3 个,
所以[1,3]有 2+1+0 个,[2,5]有 1+0+2+3 个。
【数据范围】
20%的数据满足 n<=1000,m<=10
50%的数据满足 n<=10000
100%的数据满足 n<=2000000,m<=100000
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int num[2000003],ans[2000003],tree[20000003]; int n,m,i,j,maxn,head,tail; int zhishu[100003],b[10000],p,flag[10003]; int queue[100003],step[100003]; void chuli() { zhishu[1]=1; for (int i=2;i<=10000;i++) if (zhishu[i]==0) { for (int j=i+i;j<=10000;j+=i) zhishu[j]=1; } for (int i=2;i<=10000;i++) if (zhishu[i]==0) p++,b[p]=i; } void build(int now,int l,int r) { if (l==r) { tree[now]=ans[l]; return; } int mid=(l+r)/2; build(now<<1,l,mid); build((now<<1)+1,mid+1,r); tree[now]=tree[now<<1]+tree[(now<<1)+1]; } int qsum(int now,int l,int r,int ll,int rr) { if (ll<=l&&rr>=r) { return tree[now]; } int mid=(l+r)/2; int ans=0; if (ll<=mid) ans+=qsum(now<<1,l,mid,ll,rr); if (rr>mid) ans+=qsum((now<<1)+1,mid+1,r,ll,rr); return ans; } int main() { scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d",&num[i]); maxn=max(maxn,num[i]); } chuli(); tail++; step[1]=0; queue[tail]=1; flag[1]=1; while (head<tail) { head++; int x=queue[head]; for (i=1;i<=1229;i++) { if (x*b[i]>maxn) break; if ((x*b[i])<=maxn&&flag[x*b[i]]==0) { step[x*b[i]]=step[x]+1; flag[x*b[i]]=1; tail++; queue[tail]=x*b[i]; } } } for (i=1;i<=n;i++) ans[i]=step[num[i]]; build(1,1,n); scanf("%d",&m); for (i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); printf("%d\n",qsum(1,1,n,x,y)); } }质因数分解+线段树