高精度快速幂(算法描述)

板子题:

链接

题意

求2^p-1 的后500位和位数;

位数好求,最后一位-1,如果最后一位不是0 ,则无需往前借位,然而2^p不可能出现最后一位是0的情况;所以2^p-1和2^p位数相同。

对于求a^b问题,直接快速幂就好了

然鹅,这道题的数非常大,P(1000<P<31000001000<P<3100000)。最大的一个是P=3021377P=3021377,它有909526位。

普通快速幂

long long quick(int a,int b)
{
    ans=1;
    num=a;
    while(b)
    {
        if(b&1)
            ans*=num;//只需要用数组进行模仿这两个乘法即可
        num*=num;//
        b>>=1;
    }
    return ans;
}

模仿手算

#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
int n;
int num[505],ans[505],cnt[1005];

void operator_1()
{
    memset(cnt,0,sizeof(cnt));
    for(int i=1;i<=505;i++)
        for(int j=1;j<=505;j++)
        cnt[i+j-1]+=ans[i]*num[j];//运算的规律公式
    for(int i=1;i<505;i++)
        if(cnt[i]>=10)//进位检查并进位
    {
        cnt[i+1]+=cnt[i]/10;
        cnt[i]%=10;
    }
    memcpy(ans,cnt,sizeof(ans));//终于用上了这个复制公式
}

void operator_2()
{
    memset(cnt,0,sizeof(cnt));
    for(int i=1;i<=505;i++)
        for(int j=1;j<=505;j++)
       cnt[i+j-1]+=num[i]*num[j];
    for(int i=1;i<505;i++)
    if(cnt[i]>=10)
    {
        cnt[i+1]+=cnt[i]/10;
        cnt[i]%=10;
    }
    memcpy(num,cnt,sizeof(num));
}

void quick()
{
    while(n)
    {
        if(n&1)
       operator_1();

       operator_2();
        n>>=1;
    }
}

int main ()
{
    ans[1]=1;
    num[1]=2;
    cin>>n;
    cout<<(int)(log10(2)*n+1)<<endl;
    quick();
    ans[1]-=1;
    for(int i=500;i>=1;i--)
    {
        if(i%50==0&&i!=500)
        cout<<endl;
        cout<<ans[i];
    }
    return 0;
}

原文地址:https://www.cnblogs.com/zwx7616/p/11304041.html

时间: 2024-12-30 11:13:28

高精度快速幂(算法描述)的相关文章

hdu oj 1061 Rightmost Digit (快速幂算法)

这里首先要讲解一下快速幂算法: 快速幂取模算法 在网站上一直没有找到有关于快速幂算法的一个详细的描述和解释,这里,我给出快速幂算法的完整解释,用的是C语言,不同语言的读者只好换个位啦,毕竟读C的人较多~ 所谓的快速幂,实际上是快速幂取模的缩写,简单的说,就是快速的求一个幂式的模(余).在程序设计过程中,经常要去求一些大数对于某个数的余数,为了得到更快.计算范围更大的算法,产生了快速幂取模算法.[有读者反映在讲快速幂部分时有点含糊,所以在这里对本文进行了修改,作了更详细的补充,争取让更多的读者一目

快速乘法/快速幂 算法

快速幂算法可以说是ACM一类竞赛中必不可少,并且也是非常基础的一类算法,鉴于我一直学的比较零散,所以今天用这个帖子总结一下 快速乘法通常有两类应用:一.整数的运算,计算(a*b) mod c  二.矩阵快速乘法 一.整数运算:(快速乘法.快速幂) 先说明一下基本的数学常识: (a*b) mod c == ( (a mod c) * (b mod c) ) mod c //这最后一个mod c 是为了保证结果不超过c 对于2进制,2n可用1后接n个0来表示.对于8进制,可用公式 i+3*j ==

高精度快速幂(Java版)

1 import java.io.*; 2 import java.math.*; 3 import java.util.*; 4 import java.text.*; 5 6 public class Main { 7 public static void main(String[] args) { 8 Scanner cin = new Scanner(System.in); 9 BigInteger a, b, m, ans; 10 while (cin.hasNext()) { 11

快速幂算法的理解

首先给出代码: #include <iostream> using namespace std; //计算a^bmodn int modexp(int a,int b,int n) { int ret=1; int tmp=a; while(b) { if(b&1) ret=ret*tmp%n; tmp=tmp*tmp%n; b>>=1; } return ret; } int main() { cout<<modexp(2,10,3)<<endl;

随手练——麦森数(高精度快速幂)

https://www.luogu.org/problemnew/show/P1045 第一步:求位数 第二步:高精度快速幂的实现 第一版: 用vector做的,中间把超过500位的去除,但是实际跑起来比较慢 #include <iostream> #include <stdio.h> #include <math.h> #include <vector> #include <algorithm> using namespace std; int

快速幂算法(矩阵快速幂还不是很会。。日后会更新)

PS:转载,自己写的不如人家,怕误导.转载地址:http://www.cnblogs.com/CXCXCXC/p/4641812.html 首先,快速幂的目的就是做到快速求幂,假设我们要求a^b,按照朴素算法就是把a连乘b次,这样一来时间复杂度是O(b)也即是O(n)级别,快速幂能做到O(logn),快了好多好多.它的原理如下: 假设我们要求a^b,那么其实b是可以拆成二进制的,该二进制数第i位的权为2^(i-1),例如当b==11时   a^11=a^(2^0+2^1+2^3) 11的二进制是

快速幂算法(Fast exponentiation algorithm)

对于算式an,其基本运算的时间复杂度为O(n).快速幂能将计算的复杂度降至O(log2n). Step 1. 将n拆分成二进制形式的加法: n = (2j-1 × kj) + (2j-2 × kj-1) + ... + (21 × k2) + (20 × k1) 其中,kj 为n的第j位上的数字,显然 kj = 0, 1, 2, ..., 9. Step 2. 于是,an = a2j-1×kj  +  a2j-2×kj-1  +  ...  +  a21×k2  +  a20×k1    = (

Fibonacci数列的快速幂算法

设Fibonacci数列定义为: 请用矩阵快速幂方法,即利用以下公式求Fibonacci数列第n项. 本题不涉及高精度数. 1 #include<stdio.h> 2 typedef struct matrix{ 3 int m[2][2]; 4 }matrix; 5 6 matrix multi(matrix a, matrix b) 7 { 8 int i, j, k; 9 matrix tmp; 10 for( i = 0; i < 2; ++i) 11 { 12 for( j =

快速幂算法

求超大次幂的算法,可将时间复杂度从O(N)降为 O(log?N) 百科里有很清晰的介绍: http://baike.baidu.com/link?url=x4vZ0RoaOyeRqi9vT4vYICe6uy8SeHhB1i6cCHPHTWBEcbdzGG06G8McAymojBn9Aq_1-PU_CVsww39dvmyPI_ int pow4(int a,int b) { int r=1,base=a; while(b!=0) { if(b&1) r*=base; base*=base; b>