1933: 赶时间而加上的题目
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 15 Solved: 4
[ Submit][ Status][ Web Board]
Description
两名士兵正在玩一场游戏。 首先,他们中的第一个士兵选择正整数n并将其交给第二名士兵。
然后第二个尝试使游戏有最大可能的回合数。 每一个回合包括选择一个正整数x> 1,
使得n可以被x整除并用n / x代替n。 当n等于1,并且没有更多可能的有效移动游戏结束,
并且第二个士兵的得分等于他 进行的回合数。为了使游戏更有趣,第一名士兵选择形式一个a!/ b!
对于一些正整数a和b(a≥b)。 k!表示为k的阶乘,被定义为不大于k的所有正整数的乘积。求第二个士兵最高可能的得分
Input
第一行输入t(1≤t≤1000 000),表示有t组数据。
然后接下来t行,每个包含定义游戏值n的整数a和b(1≤b≤a≤5000 000)。
Output
对于每组数据输出第二名士兵可以获得的最高分数。
Sample Input
2
3 1
6 3
Sample Output
2
5
【分析】
题意不难..就是给你一个n=a!/b!,每次选一个它的因子x,然后n/x,想要回合数最多也就是每次除质因子就好了..
所以题目就是让你求一下n的质因子有多少个,然后因为a!/b!比较大,所以考虑一下可以求出f[i]也就是i的质因子个数.
n=a!/b!=(b+1)*(b+2)*...(a)所以n的质因子个数就是f[b+1]+f[b+2]...f[a]
所以用sum[i]表示f[1]+f[2]...+f[i]
ans=sum[a]-sum[b].
所以就是求500W质因子个数的问题了...本来交Eratosthenes筛法想吃一个T看看想法对不对的...结果评测机太强势直接给过了....下面给两个代码...一个是Eratosthenes筛法O(nlogn),一个是欧拉筛法O(n)
Eratosthenes筛法直接用while求质因子个数就可以了,在复杂度上需要再乘一个常数也就是O(nlogn*k)
欧拉筛法的算法就是O(n),没有影响,对目标i*prime[j],f[i*prime[j]]+=f[i]+1;
【代码】
Eratosthenes筛法 1200ms
#include <iostream>
#include <map>
#include <cstring>
#include <cmath>
#include <cstdio>
using namespace std;
const int n=5005000;
bool vis[5005000]={0};
int f[5005000]={0};
long long sum[5005000]={0};
void init()
{
vis[1]=0;
vis[2]=0;
int x;
for (int i=2;i<5000010;i++)
if (!vis[i])
{
f[i]=1;
for (int j=i+i;j<=5000010;j+=i)
{
vis[j]=1;
x=j;
while (x%i==0) f[j]++,x/=i;
}
}
sum[1]=0;
for (int i=2;i<5000010;i++)
sum[i]=sum[i-1]+f[i];
}
int main()
{
init();
int pp;scanf("%d",&pp);
while (pp--)
{
int x,y;
scanf("%d%d",&x,&y);
printf("%lld\n",sum[x]-sum[y]);
}
return 0;
}
欧拉筛法 692ms
#include <iostream>
#include <map>
#include <cstring>
#include <cmath>
#include <cstdio>
using namespace std;
const int n=5005000;
bool vis[5005000]={0};
int f[5005000]={0};
int prime[5000000]={0};
int len=0;
long long sum[5005000]={0};
void init()
{
vis[1]=0;
vis[2]=0;
int flag;
for (int i=2;i<5000010;i++)
{
flag=0;
if (!vis[i]) prime[len++]=i,f[i]=1;
for (int j=0;j<len&&(prime[j]*i<5000010);j++)
{
vis[i*prime[j]]=1;
f[i*prime[j]]+=f[i]+1;
if (i%prime[j]==0) break;
}
}
sum[1]=0;
for (int i=2;i<5000010;i++)
sum[i]=sum[i-1]+f[i];
}
int main()
{
init();
int pp;scanf("%d",&pp);
while (pp--)
{
int x,y;
scanf("%d%d",&x,&y);
printf("%lld\n",sum[x]-sum[y]);
}
return 0;
}