[数学杂题] LibreOJ #530「LibreOJ β Round #5」最小倍数

首先显然每个质数是独立的,对于 m 个 都算一次n的下界,最后取max
对于一个质数,算满足它至少出现 e 次的最小值,可以很暴力的二分,这样要两个 log O(Tmlog2V) 再卡卡常是能过的。但还有更好的解法,可以直接贪心算每次的下界:
考虑把 n 转成 p 进制,若权为 pi 的位上是 v , 则这位对答案的贡献是 vi1j=0pj
然后就贪心的从高位到低位填即可,每次填保证之后合法的最小值。
这样就是 O(TmlogV)

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=555;
int N=550,n,m,b[maxn],p[maxn];
LL ans,a[maxn];
bool vis[maxn];
void Pre(){
    for(int i=2;i<=N;i++){
        if(!vis[i]) p[++p[0]]=i;
        for(int j=1;j<=p[0]&&(LL)i*p[j]<=N;j++){
            vis[i*p[j]]=true;
            if(i%p[j]==0) break;
        }
    }
}
LL pw[maxn],w[maxn],sum_w[maxn];
LL Solve(int prm,LL m){ 
    LL res=0; int _max;
    w[1]=sum_w[1]=_max=1; pw[0]=1; pw[1]=prm;
    for(int i=2;i<=70;i++){
        pw[i]=pw[i-1]*prm;
        w[i]=w[i-1]+pw[i-1], sum_w[i]=sum_w[i-1]+w[i], _max=i;
        if(sum_w[i]*(prm-1)>m) break;
    }
    for(int i=_max;i>=1;i--){
        if(sum_w[i-1]*(prm-1)>=m) continue;
        int now=(m-sum_w[i-1]*(prm-1)+w[i]-1)/w[i];
        res+=pw[i]*now;  m-=now*w[i];
    }
    return res;
}
int _test;
int main(){
    freopen("loj530.in","r",stdin);
    freopen("loj530.out","w",stdout);
    Pre();
    scanf("%d",&_test);
    while(_test--){
        scanf("%d",&m);
        for(int i=1;i<=m;i++) scanf("%lld",&a[i]);
        ans=1;
        for(int i=1;i<=m;i++) ans=max(ans,Solve(p[i],a[i]));
        printf("%lld\n",ans);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值