幂的模运算(题解)

题目描述:
输入三个正整数a,b,c 计算a^b mod c。
输入格式:
第一行输入三个正整数a,b,c。
输出格式:
输出a^b mod c 的值。
样例输入输出:
Mod.in mod.out
2 3 5 3
数据范围:
30%的数据满足:a,c*c 在longint 范围内,b<=10000;
50%的数据满足:a,b,c*c 都在longint 范围内;
100%的数据满足:a,b,c 在longint 范围内。

这里的幂的运算,如果要循环来mod的话,复杂度就是O(b)了,时间明显不过啊。

所以,就有一种十分鬼畜的算法:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <cmath>
using namespace std;
typedef long long ll;
ll a,b,c;
ll read()
{
    ll ans = 0;
    char ch = getchar(),last = ' ';
    while(ch < '0' || ch > '9')
        last = ch , ch = getchar();
    while(ch >= '0' && ch <= '9')
        ans = ans * 10 +ch - '0' , ch = getchar();
    if(last == '-')
        ans = -ans;
    return ans; 
} 

void put(ll x) {
    if(x < 0) {
        putchar('-');
        x = -x;
    }
    if(x == 0) {
        putchar('0');
        return;
    }
    ll q[100] , nn = 0;
    while(x)
        q[++ nn] = x % 10 , x /= 10;
    while(nn)
        putchar('0' + q[nn]), --nn;
}
ll jiafa(ll a,ll b,ll c)
{
    if (a + b >= a)
       return  (a + b) % c;
    return  (a % c + b % c - c);
}

ll chengfa(ll a,ll b,ll c )
{
    if (a * b / a == b)
       return  (a * b) % c;
    ll d = 0 ;
    for (ll i = a ; b ; i = jiafa(i,i,c) , b /= 2)
    {
        if ((b % 2) != 0)
            d = jiafa(d,i,c);
    }
    return d;
}

ll mi(ll a,ll b,ll c)
{
    ll d = 1;
    for (ll i = a ; b ; i = chengfa(i,i,c),b /= 2)
    {
       if ((b % 2) != 0)
           d = chengfa(d,i,c);
    }
    return d;
}
int main()
{
  freopen("mod.in","r",stdin);
  freopen("mod.out","w",stdout);
    a = read();
    b = read();
    c = read();
    put(mi(a,b,c));
    return 0;
}

因为幂的运算是基于加与乘的基础上的,a^b就可以看成b个a相乘,所以加的mod来解决每次每个数的mod,乘的mod来解决每次乘的mod,最后mi的mod是用来将前两项整合用的。因此就可以算出a^b%c的数了。

posted @ 2018-03-31 11:22  Zhoier  阅读(929)  评论(0编辑  收藏  举报