A - LCM from 1 to n ----Light 1289

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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章