解題思路
用到了數論
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;
}