HDU 1420 蒙哥马利幂模算法

Prepared for New Acmer


蒙哥马利幂模思想:

 在幂模运算中,通常是用幂模运算转换为乘模运算。有以下两个公式:

1)a*b%n=a%n)*(b%n)%n

2)(a+b%n=a%n+b%n)%n

当我们计算D=C^15%N时,有:

C1=C*C%N=C^2%N

C2=C1*C%N=C^3%N

C3=C2*C2%N=C^6%N

C4=C3*C%N=C^7%N

C5=C4*C4%N=C^14%N

C6=C5*C%N=C^15%N

所以,幂模运算可以转化为乘模运算。继续看,我们会发现,要求D=C^E%N,要知道E何时能整除2,并不需要反复进行减一或者除二的操作,只需要验证E的二进制个位是0还是1就行了。

本题代码:
#include <cstdio>

__int64 fun(__int64 A,__int64 B,__int64 C)
{
	__int64 k = 1;
	 A%=C;
	while(B>=1)
	{
		if((B&1)!=0)
			k = (k*A)%C;
        B>>= 1;
		A = A*A%C;
	}
	return k;
}
int main(int argc, char *argv[])
{
	int n;
	scanf("%d",&n);
	__int64 A,B,C;
	while(n--)
	{
		scanf("%I64d%I64d%I64d",&A,&B,&C);
		printf("%I64d\n",fun(A,B,C));
	}
	return 0;
}


普通代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <iomanip>

using namespace std;
int main(int argc, char *argv[])
{
    int n;
    scanf("%d",&n);
    int A,B,C;
    while(n--)
    {
        scanf("%d%d%d",&A,&B,&C);
        __int64 ans = 1;
        for(int i = 1; i <= B; i++)
        {
            ans*=A;
            ans%=C;   //注意要求余,不然很容易数据溢出;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}


posted @ 2013-03-21 15:18  简洁是智慧的灵魂  阅读(600)  评论(0编辑  收藏  举报