Pascal程序笔迹:快速幂

<Pascal笔迹>>>快速幂

作者:A_Ender


[题目介绍]

求a的n次方除b的余数。

[样例输入,输出]

输入:1000000 100000 123231

输出:95734

[题目数据]

c<=b<=a<=31^2-1



{本题套路}

数据太大,会直接爆,普通的暴力完全不行。

{算法详解}

{1}这里使用到一个分治算法,将一个非常大的数据转化成一个个小数据。(乘号可以算是大数据与小数据的分界线)

如果n是基数,那么可以转换成[a^(n-1)*n]

如果n是偶数,那么又可以转换成[a^(n/2)*(a^2)]

{2}这是一个可以推理出来的公式。(乘号也可以算是大数据与小数据的分界线)

[a*b mod c=d]=[(a mod c)*(b mod c) mod c=d]

a和b可以看作是{1}的a^m和分化出来的数。

{3}基于{2}的公式,a和b可能会很大(当然不会有int64大),但用mod的话太慢了,所以这里判断偶数直接看个位是不是2的倍数就行了。

{算法演示}

3^13 [mod 4]

3^12*3

3^6*3*9

3^3*3*9

3^2*3*3*9

9*3*3*9

全部mod 4

1*3*3*1

总和[9]再mod 4

最后是1



<代码实现>

var
        n,m,k,l:int64;              //n,m,k分别为a,n,b  l为下一次分化的数
function w(aa:int64):int64;//用字符串判断个位基偶
var
        s:string;
begin
        str(aa,s);
        s:=s[length(s)];   //个位
        if (s='0')or(s='2')or(s='4')or(s='6')or(s='8') then
                exit(1)
        else
                exit(0);
end;
begin
        l:=1;
        read(n,m,k);
        repeat
                if w(m)=0 then //如果n是基数
                begin
                        dec(m);
                        l:=l*(n mod k);
                end
                else
                if w(m)=1 then //如果n是偶数
                begin
                        m:=m div 2;
                        l:=l*(n*n mod k);
                end;
                l:=l mod k; //分化的也可能会大于b
        until m<=2;
        if m=2 then  //再次判断(此部可以省略不看)
        begin
                l:=l*(n*n mod k);
                l:=l mod k;
        end;
        if m=1 then
        begin
                l:=l*(n mod k);
                l:=l mod k;
        end;
        write(l);
end.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值