首页 > 其他 > 详细

题解 P4626 【一道水题 II】

时间:2019-10-25 11:16:14      阅读:90      评论:0      收藏:0      [点我收藏+]

题目链接

模数\(1e8+7\)……甘拜下风

Solution 一道水题II

题目大意:求\(1-n\)的最小公倍数,对\(1e8+7\)取模

筛法,数论


分析:首先暴力求乘积除以\(gcd\)是不行滴,\(nlogn\)直接上天,我们考虑\(lcm\)的性质,把每个数分解质因数(有些质数指数为\(0\)),那么把这些数的\(lcm\)分解质因数后,\(lcm\)每个因子的指数应该是每个数对应因子指数的最大值

有了这个性质就很好做了,首先用筛法把\(1-N\)里面的质数筛出来,枚举所有质数\(x\),那么这个质数对答案的贡献\(x^{\lfloor log_xN\rfloor}\),快速幂算一下乘起来就好

换底公式:

\(log_xN=\frac{logN}{logx}\)

然后就是喜闻乐见的卡常时间

  • \(Trick\;1:\)对于所有质数\(x\),若\(x>\sqrt{n}\)\(\lfloor log_xN\rfloor=1\)
  • \(Trick\;2:\)埃筛肯定是会\(GG\)的,使用欧拉筛并用\(bitset\)优化内存,在\(O2\)的加持下由于对\(Cache\)更加友好,跑得比数组快得多
  • \(Trick\;3:\)由于取模运算常数较大,我们只当\(ans>mod\)时才取模
#include <iostream>
#include <bitset>
#include <cmath>
using namespace std;
typedef long long ll;
const int mod = 1e8 + 7,maxn = 1e8 + 100;
bitset<maxn + 1> vis;
int n,pri[6000000],pri_tot,sq;
ll ans = 1;
template <typename T>
inline void domod(T &x){
    if(x >= mod)x %= mod;
}
inline ll qpow(ll a,ll b){
    ll base = a,res = 1;
    while(b){
        if(b & 1)res *= base,domod(res);
        base *= base,domod(base);
        b >>= 1;
    }
    return res;
}
inline void init(){
    for(register int i = 2;i <= n;i++){
        if(!vis[i])pri[++pri_tot] = i;
        for(register int j = 1;j <= pri_tot;j++){
            if(1ll * pri[j] * i > n)break;
            vis[i * pri[j]] = 1;
            if(!(i % pri[j]))break;
        }
    }
}
int main(){
    cin >> n;
    sq = sqrt(n);
    init();
    for(int i = 1;i <= pri_tot;i++){
        ans *= pri[i] > sq ? pri[i] : qpow(pri[i],log(n) / log(pri[i])),domod(ans);
    }
    cout << ans << '\n';
    return 0;
}

题解 P4626 【一道水题 II】

原文:https://www.cnblogs.com/colazcy/p/11736357.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!