LightOJ 1289

解题思路

 用到了数论

L(x) 求的是 LCM(1,2,3.....x)
LCM  求最小公倍数
L(1) = 1

L(x+1) = { L(x) * p    if x+1 is a perfect power of prime p
         { L(x)        otherwise

上面的知识点,在纸上推演一下就可以得出结论,根据求最小公倍数的公式,分子分母在每次遇到非素数的时候能约分,而素数的次幂上下约分得到是该素数

判断素数使用素数筛预处理,这里存不下,是用的位图存储的,数据结构有自带的<bitset>,但是我自己测试的时候发现自己写的要快上不少,就没直接使用STL

#include<set>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int Maxn = 100000000 + 10;
const int maxn = 6000000 + 10;
const int shift = 5;///shift = 5 , int 四个字节, 每个字节八位, 可以代表32个数
const int MOD = 31;///在该字节中第几位需要标记
int prime[(Maxn>>shift) + 10];
int p[maxn];
unsigned int sum[maxn];
int tot;
void SetBit(int x){
    prime[x>>shift] |= (1<<(x&MOD));
}
bool GetBit(int x){
    return prime[x>>shift] & (1<<(x&MOD));
}
void isprime(){
    tot = 0;
    for(int i = 2; i <= Maxn; i++){
        if(!GetBit(i))
        {
            p[tot++] = i;
            for(int j = i + i; j <= Maxn; j += i){
            SetBit(j);
            }
        }
    }
}
unsigned int solve(int a){
    int x = upper_bound(p, p + tot, a) - p - 1;
    unsigned int ans = sum[x];
    for(int i = 0; i < tot && p[i]*p[i] <= a; i++){
        int mul = p[i];
        int del = p[i]*p[i];
        while(del/mul == p[i] && del <= a){
            mul *= p[i];
            del *= p[i];
        }
        ans = (ans * (mul/p[i]));
    }
    return ans;
}
void init(){
    sum[0] = p[0];
    for(int i = 1; i < tot; i++){
        sum[i] = sum[i-1]*p[i];
    }
}
int main(){
    isprime();
    init();
    int T;
    int a;
    int case_ = 0;
    scanf("%d", &T);
    while(T--){
       scanf("%d", &a);
       printf("Case %d: %u\n", ++case_, solve(a));
    }
    return 0;
}

发布了69 篇原创文章 · 获赞 58 · 访问量 5万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章