cf 546_d

来源:互联网 发布:北漂 知乎 编辑:程序博客网 时间:2024/06/07 00:47
D. 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.

Sample test(s)
input
23 16 3
output
25

题意分析:本题从实质上来说,就是给你两个整数a, b。求出a, a - 1, a - 2........b + 1这些整数能被拆分成多少个素数相乘,把每个的拆分结果相加起来。

例如 a = 10, b = 2. 那么ans = 1(3) + 2(4) + 1(5) + 2(6) + 1(7) + 3(8) + 2(9) + 2(10) = 14

解题思路:由于题目给的测试点t范围很大,这样就要把每个整数能拆分的个数预先处理。我个人采用动归的思想,dp[i]代表i能被拆分成的最大素数个数。所以有:如果这个数是素数,则有dp[i] = 1.否则dp[i] = dp[i / j] + 1;(i % j == 0 && j为素数)因为实质上,dp[i]和dp[i / j] 就是多了个素数j。筛选素数的时候要使用素数筛法,否则超时。另外,dp[i]最终还要处理为前i个dp[i]的和,这样给出的答案的时间复杂度就是O(1)了。

个人感受:昨晚比赛的时候思路都是有的。就是筛选素数的时候用了暴力筛选,最后dp也没有优化成和,果断被hack了TAT怪我太蠢。不过想到用dp我也是好开桑的说,和学长的代码比了下,我这个预处理CPU占用率几乎为0~~~另外,早上交的时候是用cin输入,还是没有吃够『大数据就要用scanf』的亏啊。。。。

具体代码如下:

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;#define MAXN 5000005bool is[MAXN];int dp[MAXN];int prime[MAXN],sum;  //prime记录素数!!!void init_is()     //筛选法判断素数{     sum = 0;     memset(is , true ,sizeof(is));     for(int i = 2 ; i < MAXN ; i ++ )     {          if(is[i])          {               prime[sum++] = i ;               for(int j = 2 ; j * i < MAXN ; j ++ )               is[j*i] = false ;          }     }}void init_dp()   //每个数对应的分解质因数的个数,最后求和;{     init_is();        for(int i = 2 ; i < MAXN ; i ++ )     {          if(is[i])         //是奇数,则不能分解          {               dp[i] = 1 ;               continue ;          }          for(int j = 0 ; j < sum ; j ++ )          {               if(i % prime[j] == 0)           //找到第一个可以整除i的数               {                    dp[i] = dp[ i / prime[j] ] + 1;    //当前数的因子个数等于整除他的数的因子个数加1                    break ;               }          }     }     for(int i = 3; i < MAXN ; i ++ )     dp[i] += dp[i-1];}int main(){     init_dp();     int t;     scanf("%d" , &t);     while(t -- )     {          int a , b ;          scanf("%d%d",&a,&b) ;          printf("%d\n", dp[a] - dp[b]) ;     }     return 0 ;}


0 0
原创粉丝点击