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

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

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

LL powerMod(LL x, LL k, LL m){
    LL res = 1;
    while(x %= m, k){
        if(k&1) res *= x, res %= m;
        x *= x, k >>=1;
    }
    return res;
}

但是当其中的参数变得相对大之后,单纯的快速幂可能就不能解决问题了,下面这两个题就是当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,接下来就没什么问题了。

#include <stdio.h>
#include <iostream>
#define ULL long long
using namespace std;

ULL n, m, mod;

ULL multiplyMod(ULL x, ULL k, ULL m){
    ULL res = 0;
    x %= m;
    while(k){
        if(k&1){
            res += x;
            if(res >= m)
                res -= m;
        }
        x += x;
        if(x >= m){
            x -= m;
        }
        k >>=1;
    }
    return res;
}

ULL powerMod(ULL x, ULL k, ULL m){
    ULL res = 1;
    while(k){
        if(k&1){
            res = multiplyMod(res, x, m);
        }
        x = multiplyMod(x, x, m), k >>=1;
    }
    return res;
}

int main()
{
    while(~scanf("%I64d%I64d%I64d", &n, &m, &mod)){
        printf("%I64d\n", powerMod(n, m, mod));
    }

    return 0;
}

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/

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

#include <stdio.h>
#include <string.h>
#define LL long long

int eular(int n){
	int ret = 1;
	for(int i = 2; i*i <= n;i++)
		if(n%i == 0){
			n /= i, ret *= i-1;
			while(n%i == 0)
				n /= i, ret *= i;
		}
	if(n > 1)
		ret *= n-1;
	return ret;
}

LL powerMod(LL x, LL k, LL m){
    LL res = 1;
    while(x %= m, k){
        if(k&1) res *= x, res %= m;
        x *= x, k >>=1;
    }
    return res;
}

LL n, mod;
char m[1000005];

int main()
{
    while(~scanf("%I64d%s%I64d", &n, m, &mod)){
        LL phi = eular(mod);
        int len = strlen(m);
        LL num = 0;
        for(int i = 0; i < len; ++i){
            if(len >= 10){
                num = (num*10+(m[i]-'0'))%phi + phi;
            }
            else {
                num = num*10+(m[i]-'0');
            }
        }
        printf("%I64d\n", powerMod(n, num, mod));
    }

    return 0;
}

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

时间: 2024-10-25 03:24:41

FOJ 1752 && FOJ 1759 (a^b%c 的不同情况)的相关文章

二分快速幂 [FOJ ] 1752

Problem 1752 A^B mod C Accept: 750    Submit: 3205Time Limit: 1000 mSec    Memory Limit : 32768 KB  Problem Description Given A,B,C, You should quickly calculate the result of A^B mod C. (1<=A,B,C<2^63).  Input There are multiply testcases. Each tes

FOJ 题目 2075 Substring (后缀数组求出现k次的最小字典序子串)

Problem 2075 Substring Accept: 70    Submit: 236 Time Limit: 1000 mSec    Memory Limit : 65536 KB Problem Description Given a string, find a substring of it which the original string contains exactly n such substrings. Input There are several cases.

线段树 FOJ 2174

FOJ  2174 区间跟新,区间询问: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #define lson l,mid,rt<<1 5 #define rson mid+1,r,rt<<1|1 6 7 using namespace std; 8 typedef long long LL; 9 const int N=110001; 10 int sum[N

FOJ 2105 Digits Count

题意:对一串数字进行抑或某数,和某数,或某数,统计某区间和的操作. 思路:因为化成二进制就4位可以建4颗线段树,每颗代表一位二进制. and 如果该为是1  直接无视,是0则成段赋值为0: or  如果是0 无视,是1则成段赋值为1: xor 成段亦或,1个数和0个数交换: sum 求和: #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include <

FOJ有奖月赛-2016年8月 Problem A Daxia &amp; Wzc&#39;s problem(找规律)

Problem A Daxia & Wzc's problem Accept: 42    Submit: 228Time Limit: 1000 mSec    Memory Limit : 32768 KB Problem Description Daxia在2016年5月期间去瑞士度蜜月,顺便拜访了Wzc,Wzc给他出了一个问题: Wzc给Daxia等差数列A(0),告诉Daxia首项a和公差d; 首先让Daxia求出数列A(0)前n项和,得到新数列A(1); 然后让Daxia求出数列A(

FOJ 1683 纪念SlingShot

C - 纪念SlingShot Description 已知 F(n)=3 * F(n-1)+2 * F(n-2)+7 * F(n-3),n>=3,其中F(0)=1,F(1)=3,F(2)=5,对于给定的每个n,输出F(0)+ F(1)+ -- + F(n) mod 2009. Input   第一行是一整数m,代表总共有m个cases. Output   对于每个case,输出一行.格式见样例,冒号后有一个空格. Sample Input 2 3 6 Sample Output Case 1:

Problem 2020 组合(FOJ)

Problem 2020 组合 Accept: 714    Submit: 1724Time Limit: 1000 mSec    Memory Limit : 32768 KB  Problem Description 给出组合数C(n,m), 表示从n个元素中选出m个元素的方案数.例如C(5,2) = 10, C(4,2) = 6.可是当n,m比较大的时候,C(n,m)很大!于是xiaobo希望你输出 C(n,m) mod p的值!  Input 输入数据第一行是一个正整数T,表示数据组

dp FOJ 一月月赛C ytaaa

Accept: 57    Submit: 261 Time Limit: 2000 mSec    Memory Limit : 32768 KB  Problem Description Ytaaa作为一名特工执行了无数困难的任务,这一次ytaaa收到命令,需要炸毁敌人的一个工厂,为此ytaaa需要制造一批炸弹以供使用. Ytaaa使用的这种新型炸弹由若干个炸药组成,每个炸药都有它的威力值,而炸弹的威力值为组成这个炸弹的所有炸药的最大威力差的平方,即(max-min)^2,假设一个炸弹有5个

foj 1016 无归之室

题目来源: http://acm.fzu.edu.cn/problem.php?pid=1016 分析: 图画如下: 我们可以 列出方程. 1 )   x * cos(a)  + y * sin(a)    =  A 2 )     x * sin(a )  + y * cos(a)  =  B 对方程 化简为 2 = (a + b)^2 / (x + y)^2 + (a - b)^2 / (x -y) ^2  ; 3) 式 分三种 情况 1 : x < A  && y <B