LightOJ 1289

解题思路

 用到了数论

L(x) 求的是 LCM(1,2,3.....x)
LCM  求最小公倍数
L(1) = 1

L(x+1) = { L(x) * p    if x+1 is a perfect power of prime p
         { L(x)        otherwise

上面的知识点,在纸上推演一下就可以得出结论,根据求最小公倍数的公式,分子分母在每次遇到非素数的时候能约分,而素数的次幂上下约分得到是该素数

判断素数使用素数筛预处理,这里存不下,是用的位图存储的,数据结构有自带的<bitset>,但是我自己测试的时候发现自己写的要快上不少,就没直接使用STL

#include<set>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int Maxn = 100000000 + 10;
const int maxn = 6000000 + 10;
const int shift = 5;///shift = 5 , int 四个字节, 每个字节八位, 可以代表32个数
const int MOD = 31;///在该字节中第几位需要标记
int prime[(Maxn>>shift) + 10];
int p[maxn];
unsigned int sum[maxn];
int tot;
void SetBit(int x){
    prime[x>>shift] |= (1<<(x&MOD));
}
bool GetBit(int x){
    return prime[x>>shift] & (1<<(x&MOD));
}
void isprime(){
    tot = 0;
    for(int i = 2; i <= Maxn; i++){
        if(!GetBit(i))
        {
            p[tot++] = i;
            for(int j = i + i; j <= Maxn; j += i){
            SetBit(j);
            }
        }
    }
}
unsigned int solve(int a){
    int x = upper_bound(p, p + tot, a) - p - 1;
    unsigned int ans = sum[x];
    for(int i = 0; i < tot && p[i]*p[i] <= a; i++){
        int mul = p[i];
        int del = p[i]*p[i];
        while(del/mul == p[i] && del <= a){
            mul *= p[i];
            del *= p[i];
        }
        ans = (ans * (mul/p[i]));
    }
    return ans;
}
void init(){
    sum[0] = p[0];
    for(int i = 1; i < tot; i++){
        sum[i] = sum[i-1]*p[i];
    }
}
int main(){
    isprime();
    init();
    int T;
    int a;
    int case_ = 0;
    scanf("%d", &T);
    while(T--){
       scanf("%d", &a);
       printf("Case %d: %u\n", ++case_, solve(a));
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值