【数论】【算术基本定理】[LightOJ1289]LCM from 1 to n
题目
分析:设L(n)为LCM(1,2,3……n),则有
若n+1不是 质数的完全平方,则可将质因数分解成p1^a1*p2^a2*……pn^an,对于每个pi^ai,显然<n,且两两互质,所以p1^a1*p2^a2*……pn^an|L(n),所以n+1|L(n),L(n +1)=L(n)
若n+1是质数的完全平方,则n+1=p^k,p^k不整除1….n,p^k不整除L(n),因为p^(k-1)|L(n),所以p^(k-1)*p|L(n)*p,所以L(n+1)=L(n)*p。
筛法求素数时用位图压缩节省空间。
在实现过程中,如果暴力检查一个数是不是素数的幂,显然十分慢,所以计算所有素数的前缀和,对于前缀和的用法,看注释
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define MAXP 6000000
#define MAXN 100000000
#define SHIFT 5
int p[MAXP+10],pcnt,n,T;
unsigned int sum[MAXP+10];
int f[(MAXN+10)>>SHIFT];
void SetBit(int x){
f[x>>SHIFT]|=1<<(x&((1<<SHIFT)-1));
}
bool GetBit(int x){
return f[x>>SHIFT]&(1<<(x&((1<<SHIFT)-1)));
}
void isprime(){
int i,j,t=sqrt(MAXN+0.5);
for(i=2;i<=t;i++){
if(!GetBit(i)){
p[++pcnt]=i;
for(j=i*i;j<=MAXN;j+=i)
SetBit(j);
}
}
for(;i<=MAXN;i++)
if(!GetBit(i))
p[++pcnt]=i;
}
void prepare(){
sum[0]=1;
for(int i=1;i<=pcnt;i++)
sum[i]=sum[i-1]*p[i];
}
int main()
{
isprime();
prepare();
scanf("%d",&T);
int Case=0;
while(T--){
scanf("%d",&n);
printf("Case %d: ",++Case);
unsigned int ans=1;
int cnt=1;
while(1)
{
int m=(int)pow(n+0.9,1.0/cnt); //求n的cnt次方根
if(m<2)
break;
int i=lower_bound(p+1,p+pcnt+1,m)-p; //对于前i个素数,它们的cnt次方<=n
if(p[i]!=m)
i--;
ans*=sum[i]; //相当于枚举了前i个数的cnt次方
cnt++;
}
printf("%u\n",ans);
}
}