• FOJ 1752 && FOJ 1759 (a^b%c 的不同情况)


    博客原文地址:http://blog.csdn.net/xuechelingxiao/article/details/38614491


    对于一般的求a^b%c的值,当a,b都在long long范围内,c在1e9的时候,都可以用快速幂取模进行求解。

    1 LL powerMod(LL x, LL k, LL m){
    2     LL res = 1;
    3     while(x %= m, k){
    4         if(k&1) res *= x, res %= m;
    5         x *= x, k >>=1;
    6     }
    7     return res;
    8 }
    快速幂取模

    但是当其中的参数变得相对大之后,单纯的快速幂可能就不能解决问题了,下面这两个题就是当a^b%c中某个参数变大之后出现的问题。

    FOJ 1752 A^B mod C

    题目大意:题意很简单,就是求a^b%c的结果,只是a,b,c的范围是 (1<=a,b,c<2^63)。

    思路:这个题最关键的问题是在快速幂的时候,由于a的最大值是2^63-1,所以会出现乘法溢出,这也是最容易WA的地方。

    要解决这个问题,就需要将乘法转换成加法,进行“快速乘”(暂且这么叫吧,我也不知道叫啥-。-),就是代码中的multiplyMod,接下来就没什么问题了。

     1 #include <stdio.h>
     2 #include <iostream>
     3 #define ULL long long
     4 using namespace std;
     5 
     6 ULL n, m, mod;
     7 
     8 ULL multiplyMod(ULL x, ULL k, ULL m){
     9     ULL res = 0;
    10     x %= m;
    11     while(k){
    12         if(k&1){
    13             res += x;
    14             if(res >= m)
    15                 res -= m;
    16         }
    17         x += x;
    18         if(x >= m){
    19             x -= m;
    20         }
    21         k >>=1;
    22     }
    23     return res;
    24 }
    25 
    26 ULL powerMod(ULL x, ULL k, ULL m){
    27     ULL res = 1;
    28     while(k){
    29         if(k&1){
    30             res = multiplyMod(res, x, m);
    31         }
    32         x = multiplyMod(x, x, m), k >>=1;
    33     }
    34     return res;
    35 }
    36 
    37 int main()
    38 {
    39     while(~scanf("%I64d%I64d%I64d", &n, &m, &mod)){
    40         printf("%I64d
    ", powerMod(n, m, mod));
    41     }
    42 
    43     return 0;
    44 }
    FOJ 1752

    FOJ 1759 Super A^B mod C

    题目大意:一样的求a^b%c的结果,只是b的范围变得很大了, (1<=A,C<=1000000000,1<=B<=10^1000000)。

    思路:对于这个问题,就需要用到一个公式

    A^x = A^(x % Phi(C) + Phi(C)) (mod C)

    对于这个公式,可以给出两个证明的博客,一个是aekdycoin大犇的证明:http://www.narutoacm.com/archives/a-pow-b-mod-m/

    另一个是 http://www.narutoacm.com/archives/a-pow-b-mod-m/

    有了理论支持,这个题也就不是什么问题了,代码如下。

     1 #include <stdio.h>
     2 #include <string.h>
     3 #define LL long long
     4 
     5 int eular(int n){
     6     int ret = 1;
     7     for(int i = 2; i*i <= n;i++)
     8         if(n%i == 0){
     9             n /= i, ret *= i-1;
    10             while(n%i == 0)
    11                 n /= i, ret *= i;
    12         }
    13     if(n > 1)
    14         ret *= n-1;
    15     return ret;
    16 }
    17 
    18 LL powerMod(LL x, LL k, LL m){
    19     LL res = 1;
    20     while(x %= m, k){
    21         if(k&1) res *= x, res %= m;
    22         x *= x, k >>=1;
    23     }
    24     return res;
    25 }
    26 
    27 LL n, mod;
    28 char m[1000005];
    29 
    30 int main()
    31 {
    32     while(~scanf("%I64d%s%I64d", &n, m, &mod)){
    33         LL phi = eular(mod);
    34         int len = strlen(m);
    35         LL num = 0;
    36         for(int i = 0; i < len; ++i){
    37             if(len >= 10){
    38                 num = (num*10+(m[i]-'0'))%phi + phi;
    39             }
    40             else {
    41                 num = num*10+(m[i]-'0');
    42             }
    43         }
    44         printf("%I64d
    ", powerMod(n, num, mod));
    45     }
    46 
    47     return 0;
    48 }
    FOJ 1759
  • 相关阅读:
    python的相关基本操作
    asp.net core 验证码方案
    zookeeper常用命令
    谷粒学院_day10_技术点_nacos启动和服务注册演示
    springcloud-禁止eureka的保护模式
    springcloud-服务发现Discovery
    springcloud-actuator微服务信息完善
    springcloud-支付服务集群搭建
    rbac——界面、权限
    初识rbac
  • 原文地址:https://www.cnblogs.com/Silence-AC/p/3916566.html
Copyright © 2020-2023  润新知