Codeforces-546D Soldier and Number Game 【质因子分解+打表+DP】

来源:互联网 发布:云计算和分布式计算 编辑:程序博客网 时间:2024/06/07 10:54

D. Soldier and Number Game

time limit per test3 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Two soldiers are playing a game. At the beginning first of them chooses a positive integer n and gives it to the second soldier. Then the second one tries to make maximum possible number of rounds. Each round consists of choosing a positive integer x > 1, such that n is divisible by x and replacing n with n / x. When n becomes equal to 1 and there is no more possible valid moves the game is over and the score of the second soldier is equal to the number of rounds he performed.

To make the game more interesting, first soldier chooses n of form a! / b! for some positive integer a and b (a ≥ b). Here by k! we denote the factorial of k that is defined as a product of all positive integers not large than k.

What is the maximum possible score of the second soldier?

Input
First line of input consists of single integer t (1 ≤ t ≤ 1 000 000) denoting number of games soldiers play.

Then follow t lines, each contains pair of integers a and b (1 ≤ b ≤ a ≤ 5 000 000) defining the value of n for a game.

Output
For each game output a maximum score that the second soldier can get.

Examples
input
2
3 1
6 3
output
2
5


  1. 题意:给你a,b表示a!/b! 表示的数,你每次可以对这个数除以x(x>1,且x为这个数的因子) 使他变成a!/b!/x,问你最多可以操作多少次使这个数变成1;
  2. 思路:一化简其实就是a*(a-1)*(a-2)…(a-b+1),要次数最多,那每次除的数尽量小,由算数基本定理可知:每个数都可以分解成质数的乘积,质数只有一个质因子,那么我们可以把每个数都分解质因子,质因子不可再分那么质因子的个数就是答案; 数据量较大,应该打表,10^7 N*log(n)内层循环应该对数 9973是一个素数所以找到3000以内的素数就差不多了,先打素数表,然后打质因子个数表,然后打质因子区间表;
  3. 失误:主要把一个循环放到里面了,没有打区间表,打表比较灵活,应该根据问题打适合的表 注意时间和空间复杂度 主要还是里面的占时间多一点;
  4. 代码如下:

#include<cstdio>using namespace std;const int MAXN=5e6+13;int dp[MAXN+33],prime[3000+30]={1,1},sum[MAXN+44];int main(){       int i,j,T,N,cnt=0;     for(i=2;i<=3003;++i)    {        if(!prime[i])         {           for(j=2*i;j<=3003;j+=i) prime[j]=1;           prime[++cnt]=i;//prime保存素数 覆盖前面的值         }       }    sum[1]=0;    for(i=2;i<=MAXN;++i)//10^6 必须O(Nlog(n))     {        for(j=1;prime[j]*prime[j]<=i;++j)        {            if(i%prime[j]==0)//sum[i]保存i的分解质因子的个数             {                sum[i]=sum[i/prime[j]]+1; break;//找到最小的质因子即可 dp方程             }         }        if(prime[j]*prime[j]>i) sum[i]=1;//如果i没有质因子 那么i是素数     }                                   //如果一个数不是质数 那么在2-sqrt(n)中肯定有n的因子     for(i=1;i<=MAXN;++i) dp[i]=dp[i-1]+sum[i]; //dp[i]保存[1,i]所有数的质因子分解个数     scanf("%d",&T); int a,b;    while(T--)    {        scanf("%d %d",&a,&b);//      int ans=0;  在里面就超时了 以后打表尽量保存区间信息 //      for(i=b+1;i<=a;++i)  ans+=sum[i];//      printf("%d\n",ans);        printf("%d\n",dp[a]-dp[b]);    }    return 0;} 
0 0
原创粉丝点击