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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章