code vs guard 的无聊

1279 Guard 的无聊

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 黄金 Gold
题解
题目描述 Description

在那楼梯那边数实里面,有一只 guard,他活泼又聪明,他卖萌又霸气。他每天刷题虐 场 D 人考上了 PKU,如果无聊就去数一数质数~~ 有一天 guard 在纸上写下了一串数字,他发现数出每个数有多少个质因子是非常有(wu) 趣(liao)的事情,于是快乐的开始了数质因子之旅。现在他有一个更有(wu)趣(liao)的想法, 他想知道第a个数到第b个数每个数的质因子个数之和。更有趣的是,他一共写下了200 万个数字哟。由于guard是神犇所以不屑于求如此简单的问题,现在他把问题交给了Mr.shu, 但是他不会…,如果你能回答他的问题就能获得 guard 的亲笔签名哦~~。

输入描述 Input Description

第一行 1 个数 n,表示 guard 写下了 n 个数。 第二行 n 个用空格隔开的数,表示 guard 写下的 n 个数(每个数都不大于 10000,不小 于 1)。 第三行 1 个数 m,表示 guard 的询问数。 接下来 m 行,每行一个 a 和 b,表示 guard 想知道 a 到 b(包括 a 和 b)的每个数的质 因子个数之和。

输出描述 Output Description

一共 m 行。每行一个数表示对每个询问的答案。

样例输入 Sample Input
5 
4 2 1 6 30 
2 
1 3 
2 5 
样例输出 Sample Output
3
6
数据范围及提示 Data Size & Hint

【输入输出样例说明】

 

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));
	 }
} 
质因数分解+线段树

你可能感兴趣的:(code vs guard 的无聊)