题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26999
题意:
给定一个n,求,LCM(1,2,3,.....,n)
分析:
几个数的最小公倍数等于这些数的素因子的最高次幂的乘积;
由于求1到n的所有的数的最小公倍数 ,所有的素因子为小于等于n的所有素数
因此我们至于要求出这些素数在n内的最高次幂即可。
我们可以先预处理出所有的素数的乘积,然后再乘上到n的p[i]最高次幂/p[i]。
因为是对2^32取模 我们可以用unsigned int来存。
还有一个困难时筛求素数的时候我们开不出那么大的数组 ,因此我们需要用到一个新的工具
位图,就不在这里讲解了。
位图的讲解:http://dongxicheng.org/structure/bitmap/
用位图筛素数的方法:http://blog.csdn.net/raomeng1/article/details/8520199
代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn =100000009;
typedef unsigned int UUI;
int vis[maxn/32+50];
UUI mul[5800000];
int p[5800000],cnt,n;
void init()//运用位图来筛素数+预处理素数的积
{
cnt=1;
p[0]=mul[0]=2;
for(int i=3;i<maxn;i+=2){
if(!(vis[i/32]&(1<<((i/2)%16)))){
p[cnt]=i;
mul[cnt]=mul[cnt-1]*i;
cnt++;
for(int j=i*3;j<maxn;j+=2*i)
vis[j/32]|=(1<<((j/2)%16));
}
}
}
UUI solve()
{
int pos=upper_bound(p,p+cnt,n)-p-1;//定位到第一个小于n的素数
UUI ans = mul[pos];
for(int i=0;i<cnt&&p[i]*p[i]<=n;i++){
int tmp=p[i];
int tt=p[i]*p[i];
while(tt/tmp==p[i]&&tt<=n){//得到max(p[i]^k)<=n;用tmp*p[i]会爆int;
tmp*=p[i];
tt*=p[i];
}
ans*=(tmp/p[i]);
}
return ans;
}
int main()
{
int t,cas=1;
scanf("%d",&t);
init();
while(t--){
scanf("%d",&n);
printf ("Case %d: %u\n",cas++,solve());
}
return 0;
}