zoukankan      html  css  js  c++  java
  • codeforces546D(从一个数中拆分素数)

    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 withn / 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 ofn 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

    题目大意:

    一开始N是a!/b!.每一次士兵选择一个数x,使得n变成n/x.

    他希望玩游戏的轮数尽可能的多,问给出的N最多可以玩几轮。

    思路:

    给出的Na!/b!,其中保证a>=b.那么我们的N其实就是从b+1~a之间所有数去拆分素因子的问题。

    那么我们处理出从2~5e6这些数都可以拆分出来多少素因子然后维护一个前缀和即可。

    代码:

    #include<stdio.h>
    #include<string.h>
    int s[5000050],vt[5000050];
    int init()
    {
      int i,j;
      memset(s,0,sizeof(s));
      memset(vt,0,sizeof(vt));
      for(i=2;i<=5000005;i++)// 乍一看这代码时间复杂度很高,但是细想一下代码运行次数只有2*5000000次数左右,但是我们的vt数组就将我们时间复杂度降了下来,避免了不必要的计算
      {
        if(!vt[i])//判断i是不是素数
        {
          for(j=i;j<=5000005;j+=i)//对于一个素数,只有它的倍数才能被他整除 ,节省时间
          {
            int a=j;
            while(a%i==0)//对j进行拆分
            {
              s[j]++;
              a=a/i;
            }
            vt[j]=1;//j已经经历过了或者j不是素数
          }
        }
      }
      for(i=2;i<=5000001;i++)
      s[i]=s[i-1]+s[i];
    }
    int main()
    {
      init();
      int a,b,t;
      scanf("%d",&t);
      while(t--)
      {
        scanf("%d%d",&a,&b);
        printf("%d ",s[a]-s[b]);
      }
        return 0;
    }

     乍一看这代码时间复杂度很高,但是细想一下代码运行次数只有2*5000000次数左右,

  • 相关阅读:
    [LOJ 6436][PKUSC2018] 神仙的游戏
    [BZOJ 2653] middle
    [WC2018] 州区划分
    [BZOJ 4556][Tjoi2016&Heoi2016]字符串
    [BZOJ 3514]Codechef MARCH14 GERALD07加强版 (CHEF AND GRAPH QUERIES)
    [BZOJ 4573][ZJOI 2016]大♂森林
    Problem 2322. -- [BeiJing2011]梦想封印
    [BZOJ 2555] SubString
    [日常] NOIWC2019 冬眠记
    [BZOJ 4036][HAOI2015]按位或
  • 原文地址:https://www.cnblogs.com/cglongge/p/8893701.html
Copyright © 2011-2022 走看看