NEU1694: Primorial vs LCM

链接:http://acm.neu.edu.cn/hustoj/problem.php?id=1694

题意:给定多个n,求LCM(1~n)/pi{pi为1~n中的素数}。

分析:因为n太大有10^14,我们得观察一些性质才行。因为要求的是最小公倍数然后除掉所有的质数,这里很明显大于sqrt(n)的素数就没意义了,因为最后答案中留下的只能是指数大于1的素数。那么我们就将素数范围缩小到了10^7,然后我们再来看看有什么其他的性质,我们会知道素数p在答案中的贡献应该是p^k<=n<p^(k+1)时的p^(k-1),并且明显会有小质数的贡献质数k>=大质数的k,有了这些我们就能处理出2^2,2^3,3^3等等这些数了,比如:(4,2),(8,2),(9,3),(16,2),(25,5)。。。假设n=10,那我们找到小于它的第一个值(9,3)那么答案就是2*2*3啦,当n=26时找到(25,5)答案就是2*2*3*2*5啦。详见代码。

代码:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=10000010;
const int MAX=1000000100;
const int mod=100000000;
const int MOD1=1000000007;
const int MOD2=1000000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=1000000007;
const int INF=1000000010;
typedef double db;
typedef unsigned long long ull;
struct node {
    ll x,y,z;
    node(){}
    node(ll x,ll y):x(x),y(y){}
    bool operator < (const node a) const{
        return x<a.x;
    }
}f[700000];
int g,a[N],q[N];
void deal(ll n) {
    int i,j,k=0;
    ll mul;
    memset(q,0,sizeof(q));
    for (i=2;i<=n;i++) {
        if (!q[i]) a[++k]=i;
        for (j=1;j<=k;j++) {
            if ((ll)a[j]*i>n) break ;
            q[a[j]*i]=1;
            if (i%a[j]==0) break ;
        }
    }
    n=n*n;
    for (i=1;i<=k;i++) {
        mul=(ll)a[i]*a[i];
        f[++g]=node(mul,a[i]);
        while (log(mul)+log(a[i])<=log(n)) {
            f[++g]=node(mul*a[i],a[i]);mul*=a[i];
        }
    }
    sort(f+1,f+g+1);f[1].z=2ll;
    for (i=2;i<=g;i++) f[i].z=f[i-1].z*f[i].y%MOD;
}
ll getans(ll n) {
    if (n<4) return 1ll;
    if (n>=f[g].x) return f[g].z;
    int l=1,r=g,mid=(l+r)>>1;
    while (l+1<r)
    if (f[mid].x>n) { r=mid;mid=(l+r)>>1; }
    else { l=mid;mid=(l+r)>>1; }
    return f[l].z;
}
int main()
{
    int i,t,ca;
    ll n,ans;
    deal(10000000ll);
    scanf("%d", &t);
    for (ca=1;ca<=t;ca++) {
        scanf("%lld", &n);
        printf("Case %d: %lld\n", ca, (getans(n)+MOD)%MOD);
    }
    return 0;
}


你可能感兴趣的:(NEU1694: Primorial vs LCM)