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;
}
题目大意:求 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;
}
相关文章推荐
- 51nod 1441 士兵的数字游戏【素数筛】
- 51nod 1441:士兵的数字游戏
- 51nod 1441:士兵的数字游戏
- 1441 士兵的数字游戏 51nod
- [51nod-1441]士兵的数字游戏 题解
- 51nod 1441 士兵的数字游戏
- 51nod-1441 士兵的数字游戏
- 51Nod-1441-士兵的数字游戏
- 51nod 1441 士兵的数字游戏 (模拟线性筛)
- 1441 士兵的数字游戏
- 1441 士兵的数字游戏
- 1441 士兵的数字游戏
- 51nod 1459 迷宫游戏 dijkstra变形
- 51nod 1536不一样的猜数游戏 O(n)素数筛选法。同Codeforces 576A Vasya and Petya's Game。
- 迷宫游戏 51Nod - 1459 【最短路变形】
- 士兵的数字游戏
- 51nod1441 士兵的数字游戏 分解质因子
- 51nod 1354 选数字 (01背包变形)
- 51nod 1459 迷宫游戏Dijkstra变形
- 51nod1441 士兵的数字游戏