快速幂&快乘 HDU 5187

//快速幂
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
using namespace std;

int main()
{
    long long a,b,c;
    while(~scanf("%lld%lld",&a,&b))
    {
        c=1;
        while(b)
        {
            if(b&1)
                c*=a;
            b>>=1;
            a*=a;
        }
        printf("%lld\n",c);
    }
}

//快乘
#include<stdio.h>
#include<string.h>
#define LL long long
const LL mod=1e10;
LL cheng(LL x,LL y)
{
    LL ans=0;
    x%=mod;
    while(y)
    {
        if(y&1)
            ans+=x;
        if(ans>=mod)
            ans-=mod;
        x<<=1;
        if(x>=mod)
            x-=mod;
        y>>=1;
    }
    return ans;
}
int main()
{
    LL a,b;
    while(~scanf("%lld%lld",&a,&b))
    {
        LL ans=cheng(a,b);
        printf("%lld\n",ans);
    }
}

对于结果数据特别大的数据,利用快乘可以解决爆long long的问题。

题目描述

什么?听说你会快速幂?这么厉害的吗,那我就出一道快速幂的题吧!

题意很简单,给你n,m的值,我想知道n的m次方是多少,但是这个答案太大了,所以你只需要输出答案最后面的十位数字即可。

输入

T组输入,接下来的T行(T<300),每一行输入n,m(0<n<=100  ,0<=m<=1000000000)

输出

输出T行,每一行输出n^m的后十位数字(不够10位用零补)。

样例输入

3
2 10
3 3
1 1000000000

样例输出

0000001024
0000000027
0000000001
    #include<stdio.h>
    #include<string.h>
    #define LL long long
    const LL mod=1e10;
    LL cheng(LL x,LL y)
    {
        LL ans=0;
        x%=mod;
        while(y)
        {
            if(y&1)
                ans+=x;
            if(ans>=mod)
                ans-=mod;
            x<<=1;
            if(x>=mod)
                x-=mod;
            y>>=1;
        }
        return ans;
    }
    LL pow(LL x,LL y)
    {
        LL ans=1;
        x%=mod;
        while(y)
        {
            if(y&1)
                ans=cheng(ans,x);
            x=cheng(x,x);
            y>>=1;
        }
        return ans;
    }
    int main()
    {
        LL m,n;
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%lld%lld",&m,&n);
            printf("%010lld\n",pow(m,n));
        }
    }



//大佬的代码
#include<cstdio>  
#include<iostream>  
#include<cstring>  
#include<algorithm>  
#define LL long long  
#define mod 10000000000  
using namespace std;  
//举个栗子:(a)6541341165*(b)9846541356  
//将b拆开拆成,9,8,4,6,5,4,1,2,5,6  
//然后把a*b变成:a*6+a*10%mod*5+a*10%mod*10%mod*2+a*10%mod*10%mod*10%mod*1+.....以此类推  
//这样就能解决a*b会爆LL的问题了。  
LL chengfa(LL a,LL b)  
{  
    LL sum=0;  
    while(b)  
    {  
        sum=(sum+a*(b%10))%mod;  
        a=a*10%mod;  
        b=b/10;  
    }  
    return sum;  
}  
//LL chengfa(LL a,LL b)//如果mod为1e18的话就必须这样写了,用二进制解决这个问题  
//{  
//    LL sum=0;  
//    while(b)  
//    {  
//        if(b%2==1) sum=(sum+a)%mod;  
//        a=(a+a)%mod;  
//        b=b/2;  
//    }  
//    return sum;  
//}//看懂后你会发现这个代码和快速幂的代码基本上一样。*和+的区别。  
LL pow(LL a,LL b)  
{  
    LL sum=1;  
    while(b)  
    {  
        if(b%2==1) sum=chengfa(sum,a);  
        a=chengfa(a,a);  
//这里的a是一个小于mod的数字,a可能是一个十位数的数字  
//两个十位数相乘是二十位的数字,那么就超过了LL  
//所以要想办法使得a*a不超过LL,具体看chengfa()函数。  
        b=b/2;  
    }  
    return sum;  
}  
int main()  
{  
    int n;  
    scanf("%d",&n);  
    while(n--)  
    {  
        int a,b;  
        scanf("%d%d",&a,&b);  
        printf("%010lld\n",pow((LL)a,(LL)b));  
    }  
    return 0;  
}



再来看另一道题:

As one of the most powerful brushes, zhx is required to give his juniors n problems.
zhx thinks the ith problem's difficulty is i . He wants to arrange these problems in a beautiful way.
zhx defines a sequence {ai} beautiful if there is an i that matches two rules below:
1: a1..ai are monotone decreasing or monotone increasing.
2: ai..an are monotone decreasing or monotone increasing.
He wants you to tell him that how many permutations of problems are there if the sequence of the problems' difficulty is beautiful.
zhx knows that the answer may be very huge, and you only need to tell him the answer module p

.
Input
Multiply test cases(less than 1000 ). Seek EOF as the end of the file.
For each case, there are two integers n and p separated by a space in a line. ( 1n,p1018
)
Output
For each test case, output a single line indicating the answer.
Sample Input
2 233
3 5
Sample Output
2
1  
Hint
In the first case, both sequence {1, 2} and {2, 1} are legal.
In the second case, sequence {1, 2, 3}, {1, 3, 2}, {2, 1, 3}, {2, 3, 1}, {3, 1, 2}, {3, 2, 1} are legal, so the answer is 6 mod 5 = 1
题意:1-n排列,数列的顺序先递增后递减后者先递减后递增,问满足条件的数列有几种。

思路:只要确定数列的最大值所在的位置后者最小值所在的位置即可,其他的数放置在最值的两边,每个数都有两种情况。最后的结果取余p。

那么这道题的解法也同样是快速幂+快乘了。

#include<stdio.h>
#include<string.h>
#define LL long long
LL p;
LL cheng(LL x,LL y)
{
    LL ans=0;
    x%=p;
    while(y)
    {
        if(y&1)
            ans+=x;
        if(ans>=p)
            ans-=p;
        x<<=1;
        if(x>=p)
            x-=p;
        y>>=1;
    }
    return ans;
}
LL pow(LL n)
{
    LL base=2%p,ans=1;
    while(n)
    {
        if(n&1)
            ans=cheng(ans,base);
        base=cheng(base,base);
        n>>=1;
    }
    return ans;
}
int main()
{
    LL n;
    while(~scanf("%lld%lld",&n,&p))
    {
        printf("%lld\n",(pow(n)-2+p)%p);
    }
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值