zoukankan      html  css  js  c++  java
  • PowMod (欧拉推式子 + 指数循环节)

    最主要的步骤是用 1式子和2式子推 3式子。(难点,看了很多博客最后的时候那个式子看不懂)

    1. 当n, m互质时即gcd(n, m) == 1,存在phi(n * m) = phi(m) * phi(n)
    2. 当m为素数且n%m == 0时,存在phi(n*m) = phi(n) * m
    3. 记  为S(n, m),存在S(n,m) = S(n/p, m) * (p – 1) + S(n, m/p) (其中p为素数)
    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    
    const int MAXN = 1e7 + 9;
    const int mod  = 1e9 + 7;
    bool check[MAXN];
    int phi[MAXN], prime[MAXN], tot;
    LL sum[MAXN],now[MAXN];
    
    LL myPow(LL a, int p, LL mod){
        LL ret = 1;
        while(p){
            if(p & 1) ret = ret * a % mod;
            a = a * a % mod;
            p >>= 1;
        }
        return ret;
    }
    
    void phi_and_prime_table(int N) {
        memset(check,false,sizeof(check));
        phi[1] = 1;
        tot = 0;
        for(int i = 2; i <= N; i++) {
            if( !check[i] ) {
                prime[tot++] = i;
                phi[i] = i - 1;
            }
            for(int j = 0; j < tot; j++) {
                if(i * prime[j] > N)
                    break;
                check[i * prime[j]] = true;
                if( i % prime[j] == 0) {
                    phi[i * prime[j]] = phi[i] * prime[j];
                    break;
                } else {
                    phi[i * prime[j]] = phi[i] * (prime[j] - 1);
                }
            }
        }
        for(int i = 1; i <= N; i ++){
            sum[i] =  (sum[i - 1] + phi[i]) % mod;
        }
    }
    
    LL S(int n, int m){
        if( n == 1 ) return sum[m];
        if( m == 0 ) return 0;
        for(int i = 0; i < tot && prime[i] <= n; i ++){
            if( n % prime[i] == 0 ) {
                int p = prime[i];
                return (( 1LL * (p - 1) * S(n/p, m))%mod + S(n, m/p) % mod ) % mod;
            }
        }
    }
    
    LL A(int k,int p){
        if(k == 1) return 1;
        if(p == 1) return 0;
        return myPow(k, phi[p] + A(k, phi[p]), p);
    }
    
    int main() {
        phi_and_prime_table(10000000);
        int n,m,p;
        while(~scanf("%d%d%d",&n,&m,&p)){
            int k = S(n,m);
            printf("%lld
    ",A(k, p));
        }
        return 0;
    }
    more crazy more get!
  • 相关阅读:
    k6负载测试学习知识
    52条SQL语句性能优化策略(转)
    JVM学习
    jsonp劫持
    Airtest API精讲之keyevent()
    Airtest API精讲之Android自定义手势
    Airtest API精讲之text()
    Airtest之调用其他脚本——using()如何使用
    Airtest API精讲之wait(),exists()
    Airtest API精讲之报告日志log()
  • 原文地址:https://www.cnblogs.com/wethura/p/9727300.html
Copyright © 2011-2022 走看看