1. 程式人生 > 其它 >杭電oj人見人愛A^B

杭電oj人見人愛A^B

技術標籤:oj

杭電oj人見人愛A^B

最先想到的就是pow()函式,但是在測試過程中發現pow()函式對輸入的資料有諸多限制,可能導致錯誤的情況:
1.如果底數 x 為負數並且指數 y 不是整數,將會導致 domain error 錯誤。
2.如果底數 x 和指數 y 都是 0,可能會導致 domain error 錯誤,也可能沒有;這跟庫的實現有關。
3.如果底數 x 是 0,指數 y 是負數,可能會導致 domain error 或 pole error 錯誤,也可能沒有;這跟庫的實現有關。
4.如果返回值 ret 太大或者太小,將會導致 range error 錯誤。

解決方案:同餘方程&快速冪取模演算法

同餘方程:
因要求輸出最後三位數字,故在運算時,只取最後三位數字進行運算。

#include<iostream>
using namespace std;
int main()
{
    int m,n,r;
    while(cin>>m>>n&&(n||m))
    {
        r=1;
        m%=1000;       
        for(int i=1;i<=n;i++)
            r=r*m%1000;     
        cout<<r<<endl;
    }
return 0; }

快速冪取模演算法:
1.模運算與乘法的性質

乘積取模可以在乘之前先取模

x * y % d = ((x % d) * (y % d)) % d;

比如:a*a%c = ((a % c) * ( a % c)) % c;

2.本題公式

當b為偶數時:ab mod c = ((a2)b/2) mod c
當b為奇數時:ab mod c = ((a2)b/2× a) mod c

因此快速冪實際是分治演算法,每次將b分一半,直到b=0;):

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio> #include<iomanip> #include<algorithm> using namespace std; typedef long long ll; ll quick_mod(ll m,ll n,ll k) { if(n==0) return 1; if(n%2==1) return m*quick_mod(m,n-1,k)%k; else { ll num=quick_mod(m,n/2,k); return num*num%k; } } int main() { ll a,b,c; c=1000; while(cin>>a>>b) { ll base=quick_mod(a,b,c); cout<<base<<endl; } return 0; }