LightOj 1289 - LCM from 1 to n(LCM + 素数)

题目链接:http://lightoj.com/volume_showproblem.php?problem=1289

题意:求LCM(1, 2, 3, ... , n)%(1<<32), (1<n<=1e8);

LCM(1, 2, 3, ... , n) = n以内所有素数的最高次幂之积,例如15: 23*32*5*7*11*13 = 36360360;

为了防止TLE所以,要有一个数组表示前缀积,但是直接开LL会MLE是,因为有个%1<<32刚好是unsigned int之内,可以开int的数组;

关于求1e8内的素数表,用bool类型也会MLE的,所以可以使用bitset类型;

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <bitset>
#include <iostream>
#include <time.h>

typedef long long LL;

using namespace std;

const int N = 1e8+1;
const double eps = 1e-10;
const int INF = 0x3f3f3f3f;
const LL mod = (1ll<<32);

int k, p[6000005];
unsigned int  Mul[6000005];
bitset<N> f;

void Init()
{
    f.reset();
    for(int i=2; i<N; i++)
    {
        if(f[i]) continue;
        p[k++] = i;
        for(int j=i+i; j<N; j+=i)
            f[j] = 1;
    }
}

int main()
{
    int T, t = 1;
    scanf("%d", &T);

    Init();

    Mul[0] = p[0];
    for(int i=1; i<k; i++)
        Mul[i] = Mul[i-1]*p[i];

    while(T --)
    {
        int n;

        scanf("%d", &n);

        int pos = upper_bound(p, p+k, n)-p - 1;

        LL ans = Mul[pos];

        for(int i=0; i<k && (LL)p[i]*p[i]<=n; i++)
        {
            LL num = 1;
            while(num <= n)
                num *= p[i];
            if(num%(p[i]*p[i]) == 0) num /= (p[i]*p[i]);
            ans = ans*num%mod;
        }

        printf("Case %d: %lld\n", t++, ans);
    }
    return 0;
}
View Code

还有一种比较快一点的方法:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <bitset>
#include <iostream>
#include <time.h>

typedef long long LL;

using namespace std;

const int N = 1e8+1;
const double eps = 1e-10;
const int INF = 0x3f3f3f3f;
const LL mod = (1ll<<32);

int k = 0, p[6000005], f[N/32+5];
unsigned int  Mul[6000005];

void Init()
{
    p[k++] = 2;
    for(int i=3; i<N; i+=2)
    {
        if(f[i/32]&(1<<((i/2)%16)))
            continue;
        p[k++] = i;
        for(int j=3*i; j<N; j+=2*i)
            f[j/32] |= (1<<((j/2)%16));
    }
    ///printf("%d\n", k);
}

int main()
{
    int T, t = 1;
    scanf("%d", &T);

    Init();

    Mul[0] = p[0];
    for(int i=1; i<k; i++)
        Mul[i] = Mul[i-1]*p[i];

    while(T --)
    {
        int n;

        scanf("%d", &n);

        int pos = upper_bound(p, p+k, n)-p - 1;

        LL ans = Mul[pos];

        for(int i=0; i<k && (LL)p[i]*p[i]<=n; i++)
        {
            LL num = 1;
            while(num <= n)
                num *= p[i];
            if(num%(p[i]*p[i]) == 0) num /= (p[i]*p[i]);
            ans = ans*num%mod;
        }

        printf("Case %d: %lld\n", t++, ans);
    }
    return 0;
}
View Code

 

posted @ 2016-11-04 15:50  西瓜不懂柠檬的酸  Views(203)  Comments(0Edit  收藏  举报
levels of contents