您的位置:首页 > 其它

51nod 1441 士兵的数字游戏 (素数筛变形)

2017-11-14 12:44 246 查看
传送门51nod 1441

题目大意:求 n 的质因子的个数和,质因子可以相同。其中 n = a! / b!。

思路

首先看下数据大小,一共有 1000000 组测试数据,虽然有 6 秒的时间,但是如果对每组数据都临时处理的话必须要求处理每组的时间复杂度为 O(1),所以很容易想到这道题应该进行预处理。

要求 n 的质因子个数,而 n 又可以由两个阶乘表示,我首先想到的是一个性质:n! (n的阶乘)的素因子分解中的素数 p 的幂为 [n/p]+[n/p^2]+[n/p^3]+……,其中 p^i <= n, [ ] 为向下取整。于是我就先把素数表打出来,对 n! 看它有多少个质因子,答案就是 a! 和 b! 的质因子数之差。 然鹅……时间爆掉了。

然后从网上找答案,找到了一种新的思路。之前是对每个数都进行分解质因子,现在要对每个质因子影响的每个数的质因子数都 +1 。这样是以每个质因子为主体,会大大节省时间。这样做的时间大约为 2.5s,而排行榜的第一名驴蛋蛋大神竟然只用了不到 1s,Orz……

具体实现

n = (b+1)*(b+2)*……*(a-1)*a,所以我们预处理一下,对于每个质数我们去计算为该质数倍数的数中该质因子的个数。结束后就求出了每个数的质因子个数,求前缀和,对于输入的每对 a、b,则答案就是两个前缀和之差 sum[a]-sum.

[b]代码


#include<stdio.h>
#include<string.h>

int pri[5000010],sum[5000010];

void init()
{
int i,j,tmp;
memset(pri,1,sizeof(pri));
for(i=2;i<=5000000;i++)
if(pri[i])
{ //如果是质数
for(j=i;j<=5000000;j+=i)
{ //注意是从 j=i 开始
tmp=j;
while(tmp%i==0)
{ //计算 j 里有多少个质因子 i
tmp/=i;
sum[j]++; //质因子数 +1
}
pri[j]=0;
}
}
for(i=1;i<=5000000;i++) //前缀和
sum[i]=sum[i]+sum[i-1];
}

int main()
{
int t,a,b,ans;
init();
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&a,&b);
ans=sum[a]-sum[b];
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: