Given an integer n, you have to find
lcm(1, 2, 3, ..., n)
lcm means least common multiple. For example lcm(2, 5, 4) = 20, lcm(3, 9) = 9, lcm(6, 8, 12) = 24.
Input
Input starts with an integer T (≤ 10000), denoting the number of test cases.
Each case starts with a line containing an integer n (2 ≤ n ≤ 108).
Output
For each case, print the case number and lcm(1, 2, 3, ..., n). As the result can be very big, print the result modulo 232.
Sample Input
5
10
5
200
15
20
Sample Output
Case 1: 2520
Case 2: 60
Case 3: 2300527488
Case 4: 360360
Case 5: 232792560
Sponsor
題意:給一個數n,求1~n 這n個數的最小公倍數。
例:n=10,求 LCM(1,2,3,4,5,6,7,8,9,10)。
針對於這10 個數進行分解有如下結果:
1 2 3 4 5 6 7 8 9 10
分解後: 1 2 3 2*2 5 2*3 7 2*2*2 3*3 2*5
可以看出 對於(2,4,8)這三個 數,只需要8就可以了。對於(3,9),只需要9 就可以了, 對於(5,10),只需要10就可以了,
那就剩下6和7了。對於6,那麼找到(8,9)的最小公倍數就一定是6的倍數,所以6可以不考慮。那麼就剩下(7)了。 綜上,只要找到LCM(8,9,5,7)就完成了。四個數中不存在最大公約數,所以LCM(8,9,5,7)=8*9*5*7;即 pow(2,3)*pow(3,2)*5*7。由此可以得出要求1~n的最小公倍數【只需要求出n之前的素數的最高次冪小於n的乘積就可以了】。
想要求1e8內的素數用素數篩 進行打表時,book 數組就不可以使用了。這裏使用了一個 函數bitset.【頭文件 bitset】;
bitset<2>表示 二進制的長度爲2。 初始化每位上爲0。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<bitset>
using namespace std;
const int N=1e8+10;
bitset<N>book;
unsigned int sum[5800000];
int su[5800000];
int r=0;
void prime()
{
for(int i=2; i<N; i++)
{
if(book[i]==0)
su[r++]=i;
for(int j=0; j<r&&i*su[j]<N; j++)
{
book[i*su[j]]=1;
if(i%su[j]==0)
break;
}
}
sum[0]=2;
for(int i=1; i<r; i++)
sum[i]=sum[i-1]*su[i];
}
unsigned int quick_pow(int a,int b)
{
unsigned int res=1;
while(b)
{
if(b&1)
res=res*a;
a=a*a;
b=b/2;
}
return res;
}
int main()
{
prime();
int t,o=1;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
int id=upper_bound(su,su+r,n)-su-1;//找到第一個大於n的素數的位置,減去1,就找到了小於n的素數
unsigned int ans=sum[id];
for(int i=0; i<r&&su[i]*su[i]<=n; i++)
{
int m=n;
int num=0;
while(m/su[i])//求每個素數的個數
{
m=m/su[i];
num++;
}
num--;//因爲前綴積裏面含有一個所以每個素數的個數要減去1
ans*=quick_pow(su[i],num);
}
printf("Case %d: %u\n",o++,ans);
}
return 0;
}