【数论】【算术基本定理】[LightOJ1289]LCM from 1 to n

来源:互联网 发布:tr罗马布特黑淘宝 编辑:程序博客网 时间:2024/06/14 22:56

题目
分析:设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 5int 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);    }}
0 0
原创粉丝点击