题目链接: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; }
时间: 2024-10-09 13:50:59