#欧拉余数定理算法

对于 A^B mod C
(网上的算法基本上不见考虑 A ,C 不互质的情况,显然是残缺的)

1.如果 A ,C 不互质(互质:两个数做因式分解,公共因子只有1)
通过约分使得新的C1与A互质,如果C1与A不互质,则重复此步骤。
记录的约数积Y 和商S积

2 如果 A 大于 C ,则A = A %C

3 求C的欧拉函数值euler

4 如果B不小于euler, B=B%euler

5 计算 e=A^B ,此时A,B已经较小了

6 A^B mod C =(e*S %C)*Y

举个例子 :15 ^6mod12 = 9

  •   A=15
    
  •   B=6
    
  •   C=12
    

一,15,12有约数3:

  •   A=15
    
  •   B=B-1=5
    
  •   C=12/3=4
    
  •   Y=3
    
  •   S=15/3=5
    

二 A>C:

  •   A=A%C=15%4=3
    

三 求C的欧拉函数值:

  •   euler(4)=2
    

四 :

  •    B=B%euler=5/2=1
    

五 计算 :

  •    e=A^B  =3 ^ 1=3
    

六 :

  •   A^B  mod C =(e*S %C )*Y = 3* 5%4*3=15%4*3=3*3=9
    

代码

public class Mod {public static int  powerMod(int a,int pow,int n) {int factor=coprime(a,n);int multiplier=1;int quotient=1;int cya=a;int cyn=n;int cypow=pow;while(factor>0&&cypow>1) {multiplier*=factor;quotient*=cya/factor;cyn/=factor;cypow--;factor=coprime(cya,cyn);}if(cya>cyn) {cya%=cyn;}int euler = eulerFunction(cyn);if(cypow>euler&&euler>0) {cypow%=euler;}int ret=1;if(cya==0) {ret=0;}else if(cypow==0) {ret=1;}while(cypow>0) {ret*=cya;cypow--;}return (quotient*ret%cyn)*multiplier;}public static int  eulerFunction(int n) {if(isPrimeNumber(n)) {return n-1;}int count=0;for(int i=1;i<n;i++) {if(coprime(i,n)<0) {count+=1;}}return count;}public static int coprime(int a,int b) {int min = Mod.min(a,b);for(int i=2;i<=min;i++) {if(a%i==0) {if(b%i==0) {return i;}}}return -1;        }public static <E extends Comparable<E>> E min(E ... pars) {Objects.requireNonNull(pars);if(pars.length==0) {throw new NullPointerException();}E min=pars[0];for(int i=1;i<pars.length;i++) {if(min.compareTo(pars[i])>0) {min=pars[i];}}return min;       }
}

测试 欧拉函数

     for(int i=1;i<21;i++) {System.out.println(i+"->"+eulerFunction(i));}

1->0
2->1
3->2
4->2
5->4
6->2
7->6
8->4
9->6
10->4
11->10
12->4
13->12
14->6
15->8
16->8
17->16
18->6
19->18
20->8

测试模方法

手工单个检验无疑是不可取得,所以使用BigInteger 进行结果检验。
A C 的值一定要取小点,原因在下文。

     for(int i=1;i<10;i++) {int a=(int) (Math.random()*20);int b=(int) (Math.random()*1000+1);int c=(int) (Math.random()*20+1);System.out.println(a+" ^ "+b+" mod "+c);System.out.print("powerMod "+powerMod(a,b,c));BigInteger big=BigInteger.valueOf(a);System.out.println(" vs " +" big "+big.modPow(BigInteger.valueOf(b), BigInteger.valueOf(c)));}

13 ^ 214 mod 2
powerMod 1 vs big 1
12 ^ 178 mod 16
powerMod 0 vs big 0
6 ^ 73 mod 16
powerMod 0 vs big 0
3 ^ 890 mod 13
powerMod 9 vs big 9
6 ^ 572 mod 17
powerMod -5 vs big 13
8 ^ 805 mod 2
powerMod 0 vs big 0
15 ^ 665 mod 18
powerMod 9 vs big 9
10 ^ 290 mod 2
powerMod 0 vs big 0
17 ^ 149 mod 6
powerMod 5 vs big 5

很容易发现有个异常值:
6 ^ 572 mod 17
powerMod -5 vs big 13
不难想到原因定是整型溢出。
可以推敲一下。
euler(17)=16
572%16=12
6 ^ 12 = 3 ^ 24
int=2^31-1< 2 ^32
3 ^ 24 /2 ^ 32=(3/2) ^ 24 / (2 ^ 8 )
3/2=1.5>2 ^ (1/2)=1.414
(3/2) ^ 24 / (2 ^ 8 ) > ( 2 ^ (1/2) ) ^ 24 / (2 ^ 8 ) =2 ^ 12 / 2 ^8=16
至少大了16倍,所以必然出错。

解决方案:
将int 包装成 BigInteger 即可。

增加本算法与BigInteger.modPow()时间效率的对比,不禁感叹源码的神奇。

欧拉余数定理通解,求A的B次幂模C的值( A^B mod C)相关推荐

  1. 欧拉函数:求小于等于n且与n互质的数的个数

    求小于等于n且与n互质的数的个数 互质穷举法 互质:两个数互质代表两者最大公约数为1 最大公约数求法:辗转相除法,最小公倍数:较大值除以最大公约数乘以较小值 辗转相除法: 较大的数a取模较小的数b,得 ...

  2. 【2021牛客寒假第五场】C-比武招亲(下)欧拉降幂+多项式求逆预处理伯努利数计算等幂求和

    [2021牛客寒假第五场]C-比武招亲(下)欧拉降幂+多项式求逆预处理伯努利数计算等幂求和 前置技能 题意 思路 Code(715MS) 传送门: https://ac.nowcoder.com/ac ...

  3. 欧拉函数(求与n互质的数的个数)

    求解与n(1-n-1)互质的质因子的个数 解析:(转) 定义:对于正整数n,φ(n)是小于或等于n的正整数中,与n互质的数的数目. 例如:φ(8)=4,因为1,3,5,7均和8互质. 性质:1.若p是 ...

  4. 欧拉筛 筛法求素数 及其例题 时间复杂度O(n)

    埃式筛法尽管不错,但是确实做了许多无用功,某个数可能会被重复的筛好几次,欧拉筛解决了这个方法,下面为代码: 注意理解if(i%prim[j]==0) break; 大佬讲的不错的博客,我就不做复读机了 ...

  5. 欧拉线性筛法求素数(顺便实现欧拉函数的求值)

    标签:欧拉筛法   素数   欧拉函数   phi 我们先来看一下最经典的埃拉特斯特尼筛法.时间复杂度为O(n loglog n) int ans[MAXN]; void Prime(int n) { ...

  6. 欧拉线性筛 求n的最小正因数的个数

    由算术基本定理可得: 任何一个大于1的N的自然数,如果N不为质数,可以被分解成有限个质数的乘机,即 n=(p1a1)*(p2a2)(p3a3)*--*(pnan),在这里(p1<p2<p3 ...

  7. 利用欧拉四面体公式求任意三棱锥的体积

    OA=20.81,OB=23.9,OB=14.98,AB=15.38,BC=18.03,CA=25.37  将a=OA,b=OB,c=OC,l=AB,m=BC,n=CA 带入下式计算,利用三个棱长求体 ...

  8. Relatives POJ - 2407(不打表的欧拉函数 单求)

    Relatives POJ - 2407 题目链接:https://vjudge.net/problem/POJ-2407#author=0 题目: 给定n是一个正整数,有多少正整数小于n是n的相对素 ...

  9. spoj26246 Strange But Easy(欧拉筛选法求素数)

    用php提交超时,改为c++ #include <cstdio> #include <vector> #include <cstring>using namespa ...

最新文章

  1. 2022-2028年中国丁二烯橡胶行业市场规模研究及前瞻分析报告
  2. ibatis 配置参数解析
  3. 吃西餐的吴大师略懂《赤壁》
  4. Oracle中用一个序列给两个表创建主键自增功能的后果
  5. springboot使用webjars引入jquery
  6. SQL优化的若干原则
  7. c++ STL:队列queue、优先队列priority queue 的使用
  8. 取某个单元格的值_vba中如何进行单元格复制,Copy方法使用介绍,一定要学
  9. Python轻量级WEB框架web.py之操作数据库
  10. Python+OpenCV:仿射变换和透射变换
  11. python---之suplot和suplots的区别
  12. 【SQL Server】入门教程-基础篇(二)
  13. android studio 2.3.3 最新 中文 汉化包 韩梦飞沙 安卓工作室 美化包
  14. Linux共享文件夹
  15. EDEM基础操作步骤
  16. 一道求极值的三角函数题
  17. vue3 web项目引入高拍仪
  18. 跳马周游c++_C++——跳马问题(广搜)
  19. 京东商智-指数转换/指数还原
  20. linux 删除tmp文件夹,Linux下tmp文件夹的文件自动删除的问题(转)

热门文章

  1. 超简单理解自平衡二叉查找树的 旋转 是什么?
  2. C#.NET自动生成Excel图形报表
  3. python图形编程pdf_Python计算机视觉编程
  4. Java学习笔记之三——Java用户登陆界面
  5. 过路人分析:新浪微博搜索的分词技术不足
  6. 【散文】 一个人的旅行
  7. 项目实例:KNN预测电影网站用户性别(Hadoop学习笔记三)
  8. 如何开发一个C++高性能项目
  9. word 2003 发送错误报告
  10. DRF不通过pk,多个字段自定义删除