$loj530 [LibreOJ eta Round #5]$ 最小倍数 数论

正解:数论

解题报告:

传送门$QwQ$!

不想做题,来水点儿简单点的$QwQ$.

一个显然的点在于可以直接对不同质因子分别算$n_{min}$最后取$max$.

这个正确性还是蛮显然的?因为只要有$ngeq n_{min}$就一定能整除这个质因子呗$QwQ$.

现在就只要分别求这个$n_{min}$了

考虑二分呗,然后$n!$中$x$的指数之和就是$sum frac{n}{x^i}$

$over$

一个优化是从大到小枚举这个$pr$这样二分的次数少些计算就少些,不然会$T$,$QAQ$.

 

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define gc getchar()
#define ll long long
#define ri register int
#define rb register bool
#define rc register char
#define rp(i,x,y) for(ri i=x;i<=y;++i)
#define my(i,x,y) for(ri i=x;i>=y;--i)

const int N=1e4;
int pr[N+10],pr_cnt;
ll a[N];
bool is_pr[N+10];

il ll read()
{
    ll x=0;rb y=1;rc ch=gc;
    while(ch!='-' && (ch>'9' || ch<'0'))ch=gc;
    if(ch=='-')y=0,ch=gc;
    while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
    return y?x:-x;
}
il void pre(){rp(i,2,N)if(!is_pr[i]){if(pr_cnt<100)pr[++pr_cnt]=i;for(ri j=1ll*i*i;j<=N;j+=i)is_pr[j]=1;}}

int main()
{
    //freopen("530.in","r",stdin);freopen("530.out","w",stdout);
    pre();ri T=read();
    while(T--)
    {
        ri m=read();ll as=1;
        rp(i,1,m)a[i]=read();
        my(i,m,1)
        {
            ll l=as,r=1ll*a[i]*pr[i];//printf("l=%lld r=%lld %lld*%d
",l,r,a[i],pr[i]);
            while(l<r)
            {
                ll mid=(l+r)>>1,t1=0,t2=mid;while(t2 && t1<a[i])t2/=pr[i],t1+=t2;
                if(t1>=a[i])r=mid;else l=mid+1;
            }
            as=max(as,l);
        }
        printf("%lld
",as);
    }
    return 0;
}
View Code

 

原文地址:https://www.cnblogs.com/lqsukida/p/11676912.html