解题思路
用到了数论
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;
}