51NOD 1434 区间LCM(素数筛)

传送门

1434 区间LCM
题目来源: TopCoder
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 收藏 关注
一个整数序列S的LCM(最小公倍数)是指最小的正整数X使得它是序列S中所有元素的倍数,那么LCM(S)=X。
例如,LCM(2)=2,LCM(4,6)=12,LCM(1,2,3,4,5)=60。
现在给定一个整数N(1<=N<=1000000),需要找到一个整数M,满足M>N,同时LCM(1,2,3,4,…,N-1,N) 整除 LCM(N+1,N+2,….,M-1,M),即LCM(N+1,N+2,….,M-1,M)是LCM(1,2,3,4,…,N-1,N) 的倍数.求最小的M值。
Input
多组测试数据,第一行一个整数T,表示测试数据数量,1<=T<=5
每组测试数据有相同的结构构成:
每组数据一行一个整数N,1<=N<=1000000。
Output
每组数据一行输出,即M的最小值。
Input示例
3
1
2
3
Output示例
2
4
6
解题思路:

假设有质数K,可以求出t,使得K的t次方刚好小于等于m(K^t<=m)那么lcm(1,2,…,m)分解质因数中一定而且最多有t个质数K连乘,其实我们可以就是求的质数的最高次幂,这样就可以很快地吧lcm(1,2,…,m)分解质因数那么怎么把 lcm(n+1,n+2,…,m)分解质因数呢仍然假设质数K,可以求出最大的t,以及一个常数c(1<=c < K),使得 n+1<=c*K^t<=m
那么lcm(n+1,n+2,…,m)分解质因数中一定而且最多有t个质数K连乘。比如说质数3,n=16,m=22,可以求的c=2,t=2,即17<=2*3^2=18<=22,这样lcm(17,18,19,20,21,22)中最多有2个质数3连乘既然知道怎么求lcm(n+1,n+2,..,m)和lcm(1,2,..,m)了来探讨一下怎么求最小的m吧我们想让这两个lcm分解质因数后完全一样,也就是说连乘的质数个数也完全相等。也就是说,对于每个质数K都可以满足,存在c和最大的t 使得n+1<=c*K^t<=m对于大于n小于m的质数,我们假设是P,那么一定n+1<=P<=m,一定可以满足条件所以我们就只看小于等于n的质数就可以了因为要使每个小于N的质数K,都存在c和最大的t 使得n+1<=c*K^t<=m,我们枚举每一个质数,并求得c和t,使得刚好c*K^t>=n,
答案就取最大的c*K^t,即 max( c*K^t )这样lcm(1,2,…,m)和lcm(n+1,n+2,…,m)的分解质因数后均至少有t个质数K。如果最终m有 k^(t+1)<=m,那么这个K^(t+1)>n一定成立,故仍满足条件
代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 1e6+5;
LL p[MAXN];
bool prime[MAXN];
int k;
void isprime()
{
    k = 0;
    memset(prime, 0, sizeof(prime));
    prime[0] = prime[1] = 1;
    for(LL i=2; i<MAXN; i++)
    {
        if(!prime[i])
        {
            p[k++] = i;
            for(LL j=i*i; j<MAXN; j+=i)
                prime[j] = 1;
        }
    }
}
int main()
{
    isprime();
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        int ans = 2;
        for(int i=2; i<=n; i++)
        {
            if(!prime[i])///素数
            {
                int sum = i;
                while(sum <= n/i)
                    sum *= i;
                ans = max(ans, (n/sum+1)*sum);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值