[题解]LightOJ1289 LCM from 1 to n

传送门

题目描述

给出一个正整数\(n\),求\(lcm(1,2,...,n)\)\(2^{32}\)取模的结果

\((1\leq n\leq 10^8)\),数据组数\(T\leq 10^4\)

分析

把每一个数质因数分解,可以得到

\(lcm(\prod p_i^{b[1][i]},\prod p_i^{b[2][i]},...\prod p_i^{b[n][i]})=\prod p_i ^{max(b[x][i])}\)

空间限制比较小,1e8的数据欧拉筛可能MLE,那么就用1e8/32个int来判断每一位是不是质数

还有一个常数的小优化就是%\(2^{32}\)可以转化为&\((1<<32)-1\)

代码

#include<bits/stdc++.h>
#define rep(X,A,B) for(int X=A;X<=B;++X)
#define tep(X,A,B) for(int X=A;X>=B;--X)
#define LL long long
const int N=5761460;
const int M=3125010;
const int maxn=1e8;
const int MX=5;
const LL MOD=4294967296;
using namespace std;

int a[N];
unsigned int vis[M];
int p[N],cnt=0;

bool GET(int x){
    return (vis[x>>MX]>>(x&((1<<MX)-1)))&1;
}

void UPD(int x){
    vis[x>>MX]|=(1<<(x&((1<<MX)-1)));
}

void INIT(){
    for(int i=2;i<=maxn;i++){
        if(!GET(i))p[++cnt]=i;
        for(int j=1;j<=cnt&&p[j]*i<=maxn;j++){
            UPD(i*p[j]);
            if(i%p[j]==0)break;
        }
    }
    a[0]=1;
    rep(i,1,cnt){
        LL now=(1LL*a[i-1]*p[i])&(MOD-1);
        a[i]=now;
    }
}

void SOLVE(){
    int n;
    scanf("%d",&n);
    int pos=upper_bound(p+1,p+cnt+1,n)-p;
    LL res=a[pos-1];
    for(int i=1;i<=cnt&&p[i]<=n/p[i];i++){
        LL now=p[i]*p[i];
        for(;now<=n;now*=p[i])res=(res*p[i])&(MOD-1);
    }
    printf("%lld\n",res);
}

int main(){
    INIT();
    int T;
    scanf("%d",&T);
    rep(o,1,T){
        printf("Case %d: ",o);
        SOLVE();
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/SCL123/p/11837579.html
lcm