Codeforces Round #304 (Div. 2)(CF546D) Soldier and Number Game(线性筛)

题意

给你a,b(1<=b<=a<=5000000)表示a!/b!表示的数,你每次可以对这个数除以x(x>1且x为这个数的因子)使他变成a!/b!/x, 问你最多可以操作多少次使这个数变成1

http://codeforces.com/problemset/problem/546/D

思路

显然要素因子分解,但直接计算a!/b!的素因子个数太慢了,可以发现实际上是计算a(a-1)(a-2)……(b+1),而这些数之积的所有素因子个数之和是等于每个数的素因子个数之和的(相当于对每一个数除以x的操作次数之和),所以我们线性筛的时候计算一下素因子个数即可,最后用前缀和搞一搞O(1)输出。

代码

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int N=5e6+5;
const int mod=1e9+7;
const double eps=1e-8;
const double PI = acos(-1.0);
#define lowbit(x) (x&(-x))
ll sum[N];
int vis[N],prime[N],tot;
void shai()
{
    tot=0;
    memset(vis,0,sizeof(vis));
    for(int i=2;i<N;i++)
    {
        if(!vis[i])
            prime[tot++]=i,sum[i]=1;
        for(int j=0;j<tot&&prime[j]*i<N;j++)
        {
            vis[prime[j]*i]=1;
            sum[prime[j]*i]=sum[i]+1;
            if(i%prime[j]==0)
                break;
        }
    }
    for(int i=2;i<N;i++)
        sum[i]+=sum[i-1];
}
int main()
{
    std::ios::sync_with_stdio(false);
    int n;
    shai();
    scanf("%d",&n);
    while(n--)
    {
        ll a,b;
        scanf("%d%d",&a,&b);
        printf("%lld\n",sum[a]-sum[b]);
    }
    return 0;
}

posted @ 2019-09-26 00:38  MCQ1999  阅读(169)  评论(0编辑  收藏  举报