快速幂和快速乘

题目    a^b  多组输入a,b   求a^b的个位数

快速幂:

#include<stdio.h>
int ksm(long long a,long long b,long long c) 
{
    int ans=1;
    while(b)
    {
        if(b&1)
        {
            ans=(ans*a)%c;
        }
        a=(a*a)%c;
        b=b/2;
    }
    return ans;
}     
int main()
{
    long long n,m;
    while(~scanf("%lld %lld",&n,&m))
        printf("%lld
",ksm(n,m,10));
    return 0;
} 

当a,b很大的时候 在10^9时,用常规的方法就容易超时

所以就优化

首先n^x * x^y = n^(x+y),这个是显然的吧……
那么由此可以推出
n^m = n^x1 * n^x2 * ... * n^xi ,其中 x1 + x2 + ... + xi = m
那么,我们应该找到一种最优的方式把m分解,然后用可以很容易计算出来的n^x值相乘,就可以得到n^m的答案。
什么样的n^x算起来最快呢?
x = 1 , n^x = n
x = 2 , n^x = n^2
x = 4 , n^x = n^4 = (n^2)^2
x = 8 , n^x = n^8 = (n^4)^2
....
然后,我们知道任何一个数都可以轻松用1,2,4,8,16...的和表示出来,即,把这个数转为二进制即可。
那么对于任意一个n^m,我们就可以在O(log m)的时间内完成了。
For example: 求2^13
2^13 = 2^1 * 2^4 * 2^8
就可以了……
 
 
快速乘
#include<stdio.h>
long long ksm(long long,long long,long long);
long long ksc(long long,long long,long long);
int main()
{
    long long n,m;
    while(~scanf("%lld%lld",&n,&m))
        printf("%lld
",ksm(n,m,10));
    return 0;
}
long long ksm(long long a,long long b,long long c)
{
    long long ans=1;
    while(b)
    {
        if(b%2)
            ans=ksc(ans,a,10)%c;
        a=(a*a)%c;
        b/=2;    
    }
    return ans;
}
long long ksc(long long a,long long b,long long c)
{
    long long ans=0;
    while(b)
    {
        if(b%2)
            ans=(ans+a)%c;
        a=(a+a)%c;
        b/=2;    
    }
    return ans;
}

当a,b<=10^18时   快速幂也不能解决了  所以引入快速乘

沿用之前的方法,但是注意这里的模数是10^18
之前10^9*10^9 long long 可以存下

考虑到幂次可以转换成连续乘
连续乘可以转换成连续加
a^4 = a*a*a*a
a*a =(a+a+a.....a)
注意到两个10^18的数相加是可以的
同样我们得到一个快速乘

比如计算出a,2a,4a,8a,16a
每次乘二,不会爆

 
原文地址:https://www.cnblogs.com/tianming1/p/10071706.html