Codeforces J. Soldier and Number Game(素数筛)

题目描述:

Soldier and Number Game

time limit per test

3 seconds

memory limit per test

256 megabytes

input

standard input

output

standard 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

Copy

23 16 3

Output

Copy

25

思路:

这题目要求是给一个数n,求他的质因数的个数。又因为n是\(\frac{a!}{b!}\)的形式,即\(\prod_{i=b+1}^ai\)。也就是从b+1到a的每个数的质因数个数之和。刚开始最最原始的方法求,也就是从b+1开始遍历,求每个数的质因数的个数,然后加起来,求质因数用的是那种朴素的\(O(\sqrt{n})\)的做法,如果n是很大,而且t也很多(\(\leq10^{6}\)),就gg了。

然后执迷不悟,想的是问题出在了质因数分解上(好吧,确实出在了质因数分解上),打出miler_rabin和pollard-rho模板,分解质因数,可还是超时。

然后想到既然是区间性问题为什么我不用素数筛呢?但一看数据到\(5*10^{6}\),限时是3秒,这样打出来也是超时啊。因为我的印象中,一秒的循环次数大概在10^6,这样,那岂不是要5秒才能处理完素数表?

但后来的事情刷新了我的认知,真的是可以这么快的。那思路就是在筛素数时遇到合数是当前素数的倍数就不断地除以这个素数看他有几个这样的素因子。他也可能不同的素数的倍数,到时都会不断的加他素因子的个数。那么素数表打完了,我们的每个数的素因子个数也统计出来了。但这样是不够的,为什么?想一想询问的是一个区间,最大长度是\(10^6\)量级,加上询问的t,又gg了。这时就想到了前缀和处理区间问题。我们把前缀和算出来,在询问某个区间时对应的两个前后项一减就是区间内的统计结果。后来因为读入数据量比较大再加了读入优化,吸了氧(其实不吸也可以)。

我后来统计了一下初始化的时间,大概在0.4s左右,开了O2能少个100ms的样子。

代码:

#include <iostream>
#include <cstdio>
#include <memory.h>
#include <ctime>
#define max_n 5000005
using namespace std;
int t;
long long a,b;
int prime[max_n];
int num[max_n];
template<typename T>
inline void read(T& x)
{
    x=0;int f=0;char ch=getchar();
    while('0'>ch||ch>'9'){if(ch=='-')f=1;ch=getchar();}
    while('0'<=ch&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
    x=f?-x:x;
}
void init()
{
    memset(num,0,sizeof(num));
    memset(prime,-1,sizeof(prime));
    prime[0] = prime[1] = 0;
    for(int i = 2;i<=max_n;i++)
    {
        if(prime[i]==-1)
        {
            num[i]++;
            for(int j = 2*i;j<=max_n;j+=i)
            {
                prime[j] = 0;
                int tmp = j;
                while(tmp%i==0)
                {
                    num[j]++;
                    tmp/=i;
                }

            }
        }
    }
    for(int i = 2;i<=max_n;i++)
    {
        num[i]+=num[i-1];
    }
}
#pragma optimize(2)
int main()
{
    //clock_t start = clock();
    init();
    //clock_t end = clock();
    //printf("%f s\n",(double)(end-start)/CLOCKS_PER_SEC);
    read(t);
    while(t--)
    {
        read(a);
        read(b);
        printf("%d\n",num[a]-num[b]);
    }
    return 0;
}

posted @ 2019-08-12 19:34  小张人  阅读(79)  评论(0编辑  收藏
分享到: