zoukankan      html  css  js  c++  java
  • P5091 【模板】扩展欧拉定理 题解

    CSDN同步

    原题链接

    前置知识:

    欧拉筛,一些基本数论知识。

    简要题意:

    (a^b \% m).

    (1 leq a leq 10^9 , 1 leq b leq 10^{2 imes 10^7} , 1 leq m leq 10^8).

    首先,看到这个数据范围你就发现你凉凉了。

    算法一

    一个简单的弱化:

    (a,b,m leq 10^7).

    显然你 (mathcal{O}(b)) 过了。

    算法二

    一个再简单点的强化呢:

    . (a,b,m leq 10^{18}).

    你用 (mathcal{O}(log b)) 可以飞快过了 。

    算法三

    那么考虑这道题目呢?不行了吧?

    可能,(mathcal{O}(log b)) 的朴素快速幂 (+) 每次 (b) 的高精度除法 (div2) (+) 一定卡常是可以通过的。

    但是我们不要,我们只需要用一个简单的定理:

    [a^b equiv egin{cases} a^b space space space space space space space space space space space space space space space space space space space space space, b < phi(m) \ a^{b space ext{mod} space phi(m) + phi(m)} , b geq phi(m) \ end{cases}]

    先不管如何证明,考虑用这个玩意儿怎么做。

    (mathcal{O}(sqrt{m})) 的时间可以算出 (phi(m)),然后快读 (b)(b leq phi(m)) 则套公式快速幂,如果 (b < phi(m)) 只能说明 (b) 也很小,再跑一个 (log) 也没啥问题了。

    具体证明大家可以去看一下 ( ext{ouuan}) 的博客

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    inline int read(){char ch=getchar(); int f=1; while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
    	int x=0; while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x*f;}
    
    inline int remo(int m) {
    	char c; while(!isdigit(c=getchar()));
    	int x=0; bool f=0;
    	for(;isdigit(c);c=getchar()) {
    		x=x*10+c-'0';
    		if(x>=m) f=1,x%=m;
    	} return f?(x+m):x;
    }
    
    inline void write(int x) {
    	if(x<0) {putchar('-');write(-x);return;}
    	if(x<10) {putchar(char(x%10+'0'));return;}
    	write(x/10);putchar(char(x%10+'0'));
    }
    
    inline int pw(int a,int b,int m) {
    	int ans=1; while(b) {
    		if(b&1) ans=ans*a%m;
    		a=a*a%m; b>>=1;
    	} return ans;
    }
    
    signed main() {
    	int a=read(),m=read(); a%=m;
    	int phi=1,t=m,ans=1; 
    	for(int i=2;i*i<=t;i++) {
    		if(t%i) continue;
    		phi*=i-1; t/=i;
    		while(t%i==0) phi*=i,t/=i;
    	} if(t>1) phi*=t-1; //printf("%d
    ",remo(phi));
    	printf("%d
    ",pw(a,remo(phi),m));
    	return 0;
    }
    
    
    
  • 相关阅读:
    Android-通过SlidingPaneLayout高仿微信6.2最新版手势滑动返回(一)
    B树
    nyoj448 寻找最大数
    IT痴汉的工作现状22-由Dalvik虚拟机引发的口水战
    POJ 3221 Diamond Puzzle.
    CMDBuild安装及webservice接口的获取
    安卓dex 文件结构简要说明
    安装RPM包或者安装源代码包
    Java程序性能优化技巧
    [Sqlite]--&gt;数据迁移备份--从低版本号3.6.2到高版本号3.8.6
  • 原文地址:https://www.cnblogs.com/bifanwen/p/13236931.html
Copyright © 2011-2022 走看看