zoukankan      html  css  js  c++  java
  • 题解 P4626 【一道水题 II】

    题目链接

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

    Solution 一道水题II

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

    筛法,数论


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

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

    换底公式:

    (log_xN=frac{logN}{logx})

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

    • (Trick;1:)对于所有质数(x),若(x>sqrt{n})(lfloor log_xN floor=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 << '
    ';
    	return 0;
    }
    
  • 相关阅读:
    docker
    算法学习 —— 动态规划练习(二)
    算法学习 —— 动态规划练习(一)
    算法学习——动态规划讲解
    Java核心复习——CompletableFuture
    Java源码阅读(八)—— ThreadPoolExecutor
    Java源码阅读(三)—— ThreadLocal
    TensorFlow实现XOR
    实现逻辑回归-神经网络
    深度学习之Numpy整理
  • 原文地址:https://www.cnblogs.com/colazcy/p/11736357.html
Copyright © 2011-2022 走看看