ACM.快速幂取模

给你一个数a,让你求其b次连乘后的结果
当b很小时,一般的循环算法可以解决这个问题(O(B)),但是当b较大时呢
要知道1e18以上,就会long long int 也可能会溢出
而在数论方面这些数又该如何表示?怎样存储?
所以在此我们定义一个模数mod来代替输出
即a^ b=k1mod+t即t=a^b%mod
性质1:(a+b)%m=(a%m+b%m)%m
性质2:(a
b)%m=(a%m*b%m)%m

当幂很大时,我们采取分治的思想处理问题
a^ b=((a^ (b/n)) ^ n)*a ^ (b%n)
代码实现情况如下:
1非递归实现:

ll quickmod(ll a,ll b,ll c)
{
    int ret=1;
    while(b)
    {
        if(b&1)
            ret=ret*a%c;
        a=a*a%c;
        b/=2;
    }
    return ret;
}

2递归实现:

ll quickmod(ll a,ll b,ll c)
{
    if(b==1)
        return a;
    if(!(b&1))
    {
        ll t=quickmod(a,b/2,c);
        return t*t%c;
    }
    else
    {
        ll t=quickmod(a,b/2,c);
        return t*t%c*a%c;
    }
}

模板题:
NEFU-601
快速幂取模
Problem:H
Time Limit:1000ms
Memory Limit:65536K
Description
给定A,B,C,计算AB%C,这里AB代表A的B次方。
Input
输入数据有多组,每组数据一行,有3个正整数分别为A,B和C,1<=A,B,C<=1000000000
Output
输出A^B%C的值
Sample Input
2 3 5
8 2 10
Sample Output
3
4

没话说:
注意数据类型可能超出范围,用long long

#include <bits/stdc++.h>
using namespace std;
long long mi(long long n1,long long n2,long long n3)
{
    long long res=1;
    while(n2)
    {
        if(n2%2)
           res=res*n1%n3;
        n1=n1*n1%n3;
        n2/=2;
    }
    return res;
}
int main()
{
    long long a,b,c,sum=0;
    while(cin>>a>>b>>c)
    {
        sum=mi(a,b,c);
        cout<<sum<<endl;
    }
    return 0;
}

二.NEFU-1666
库特的数学题
Problem:I
Time Limit:1000ms
Memory Limit:65535K
Description
库特很喜欢做各种高深莫测的数学题,一天,她在书上看到了这么一道题。a[1]=6,a[2]=18;a[n]=2a[n-1]+3an-2,对于给出的某个数字n,求a[n]。库特一想这道题太简单了,可是看到n的范围是(n<=1e18),对于这么大范围的数,库特不知道该怎么做了,聪明的你,快来帮帮库特解决这个问题吧。(由于答案可能很大,请将答案对1e9+7(即1000000007)取模)。
Input
一个整数n(1<=n<=1e18)
Output
a[n]对1e9+7取模后的答案
Sample Input
5
Sample Output
486

先算前几个值,找到规律,就是3的n次方,最后处理较大的数值时用快速幂取模输出即可。

#include <bits/stdc++.h>
using namespace std;
long long n;
long long mi(long long a,long long b,long long c)
{
    long long res=1;
    while(b)
    {
        if(b%2)
            res=res*a%c;
        a=a*a%c;
        b/=2;
    }
    return res;
}
int main()
{
    while(cin>>n)
    {
        long long a1=mi(3,n,1000000007);
        long long a3=(a1*2)%1000000007;
        cout<<a3<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值