zoukankan      html  css  js  c++  java
  • 2 ^ x mod n = 1问题

    问题介绍:给一个整数n,找到最小的x(x > 0),使满足 2 ^ x mod n = 1

    问题解析:对于a * b % c 有公式:    a * b % c = ((a % c) * (b % c)) % c.

        所以可以通过递归求解a ^ b mod c.穷举x,便可写出以下代码:

        

     1 #include<stdio.h>
     2 #include<iostream>
     3 using namespace std;
     4 
     5 //a ^ b % c
     6 int get_mod(__int64 a, int b, int c)
     7 {
     8     if(b == 1)
     9         return a % c;
    10     return get_mod(a, b - 1, c) * a % c;
    11     //((a ^ (b - 1) % c) * a) % c
    12 }
    13 
    14 
    15 int main()
    16 {
    17     int n;
    18     while(cin>>n)
    19     {
    20         if(n % 2 == 0 || n <= 1)
    21             printf("2^? mod %d = 1
    ", n);
    22         else
    23         {
    24             int x;
    25             for(x = 1; ; x++)
    26                 if(get_mod(2, x, n) == 1)
    27                 {
    28                     printf("2^%d mod %d = 1
    ", x, n);
    29                     break;
    30                 }
    31         }
    32     }
    33     return 0;
    34 }
    35  

    显然,当n比较大时,上述算法的效率很低,最终导致超时...需要修改莫幂运算的算法.

       需要使用一种数学方法:蒙哥马利幂模运算(是快速计算a^b%k的一种算法).

         由于a * a % c =  ((a % c) * (a % c)) % c   =  ((a % c)^2) % c. 可以将两次运算转换为一次乘方运算.

         所以可以通过这样的递归公式:a ^ 2n % c = (a ^ n % c) ^ 2 % c.可以二分计算.

        效率由原来的n变为log2(n).当n很大时,效率提升数万倍.

        注意,当n为奇数时,需要利用正常的递推方法使n - 1为偶数带入下一次计算.

       修改后的代码:

       

     1 //给一个整数n,找到最小的x(x > 0),使满足 2 ^ x mod n = 1
     2 
     3 #include<stdio.h>
     4 #include<math.h>
     5 #include<iostream>
     6 using namespace std;
     7 
     8 //a ^ b % c
     9 int get_mod(__int64 a, int b, int c)
    10 {
    11     if(b == 1)
    12         return a % c;
    13     if(b % 2 == 1)
    14         return (get_mod(a, b - 1, c) * (a % c)) % c;
    15     return (int)pow(get_mod(a, b / 2, c), 2) % c; 
    16     //((a ^ (b - 1) % c) * a) % c
    17 }
    18 
    19 
    20 int main()
    21 {
    22     int n;
    23     while(cin>>n)
    24     {
    25         if(n % 2 == 0 || n <= 1)
    26             printf("2^? mod %d = 1
    ", n);
    27         else
    28         {
    29             int x;
    30             for(x = 1; ; x++)
    31                 if(get_mod(2, x, n) == 1)
    32                 {
    33                     printf("2^%d mod %d = 1
    ", x, n);
    34                     break;
    35                 }
    36         }
    37     }
    38     return 0;
    39 }
    40  
  • 相关阅读:
    Spring Cloud
    Hibernate 缓存
    Spring 快速入门
    Junit 单元测试
    Spring Cloud 笔记
    Swagger SpringBoot 集成
    Apache Shiro 权限框架
    Spring Boot
    跨域问题
    BeX5 常见问题解决办法
  • 原文地址:https://www.cnblogs.com/bmdx/p/3198256.html
Copyright © 2011-2022 走看看