快速幂

Posted meant to be

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速幂相关的知识,希望对你有一定的参考价值。

普通快速幂:

复杂度 O(log n)

模板:

#include <bits/stdc++.h>
using namespace std;
const int mod=1e5+7;
int ksm(int a,int b){
    int ans=1;
    while(b){
        if(b&1)
            ans=ans*a%mod;
        a=a*a%mod;
        a>>=1;
    }
    return ans;
}

int main(){
    return 0;
}

矩阵快速幂:

矩阵乘法:

示例如斐波那契数列:

     

其中要知道,一条对角线为1,其他为0的矩阵乘以其他矩阵其他矩阵不发生改变,即可以把他当成相乘时的1。

其中还有其他较为复杂的类型:

  

这需要用到二项式定理:

 

复杂度O(log n)

模板

#include <bits/stdc++.h>
using namespace std;
const int mod=2147493647;
int f=7;

struct node{
    int arr[10][10];
};

node mul(node x,node y){
    node ans;
    memset(ans.arr,0,sizeof(ans.arr));
    for(int i=1;i<=f;i++){
        for(int j=1;j<=f;j++){
            for(int k=1;k<=f;k++){
                ans.arr[i][j]=(ans.arr[i][j]+x.arr[i][k]*y.arr[k][j]%mod)%mod;
            }
        }
    } 
    return ans;
}

node ksm(node a,int b){
    node ans;
    memset(ans.arr,0,sizeof(ans.arr));
    for(int i=1;i<=f;i++){
        ans.arr[i][i]=1;
    }
    while(b){
        if(b&1) ans=mul(ans,a);
        a=mul(a,a);
        b>>=1;
    }
    return ans;
}

int main(){
    return 0;
}

 

例题:

D - Recursive sequence

 Farmer John likes to play mathematics games with his N cows. Recently, they are attracted by recursive sequences. In each turn, the cows would stand in a line, while John writes two positive numbers a and b on a blackboard. And then, the cows would say their identity number one by one. The first cow says the first number a and the second says the second number b. After that, the i-th cow says the sum of twice the (i-2)-th number, the (i-1)-th number, and i4i4. Now, you need to write a program to calculate the number of the N-th cow in order to check if John’s cows can make it right. 

Input

The first line of input contains an integer t, the number of test cases. t test cases follow. 
Each case contains only one line with three numbers N, a and b where N,a,b < 231231 as described above. 

Output

For each test case, output the number of the N-th cow. This number might be very large, so you need to output it modulo 2147493647.

Sample Input

2

3 1 2

4 1 10

Sample Output

85

369

题目大意:

一个人有n只牛,他会给两个数a b,第一只牛说a,第二只说b,接下来的i只都会说(i-2)只说的数的二倍,(i-1)只说的一倍,再加上i^4。通项公式为f(n)=f(n-2)*2+f(n-1)+n^4.

题解:

n^4无法直接写,因为会使常数矩阵与n有关。所以要用到二项式公式。

  

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll c[7]={1,4,6,4,1,2,1};
ll f=7;
const ll mod=2147493647;
struct aa{
    ll arr[10][10];
};

aa mul(aa x,aa y){
    aa ans;
    memset(ans.arr,0,sizeof(ans.arr));
    for(ll i=1;i<=f;i++){
        for(ll j=1;j<=f;j++){
            for(ll k=1;k<=f;k++){
                ans.arr[i][j]=(ans.arr[i][j]+x.arr[i][k]*y.arr[k][j]%mod)%mod;
            }
        }
    } 
    return ans;
}

aa ksm(aa a,ll b){
    aa ans;
    memset(ans.arr,0,sizeof(ans.arr));
    for(ll i=1;i<=f;i++){
        ans.arr[i][i]=1;
    }
    while(b){
        if(b&1) ans=mul(ans,a);
        a=mul(a,a);
        b>>=1;
    }
    return ans;
}




int main(){
    aa x,y,ans;
    ll t,n,a,b;
    cin>>t;
    while(t--){
        memset(ans.arr,0,sizeof(ans.arr));
        memset(x.arr,0,sizeof(x.arr));
        memset(y.arr,0,sizeof(y.arr));
        cin>>n;
        cin>>a>>b;
        x.arr[1][1]=1;x.arr[1][2]=2;x.arr[1][3]=1;x.arr[1][4]=4;x.arr[1][5]=6;x.arr[1][6]=4;x.arr[1][7]=1;
        x.arr[2][1]=1;x.arr[2][2]=0;x.arr[2][3]=0;x.arr[2][4]=0;x.arr[2][5]=0;x.arr[2][6]=0;x.arr[2][7]=0;
        x.arr[3][1]=0;x.arr[3][2]=0;x.arr[3][3]=1;x.arr[3][4]=4;x.arr[3][5]=6;x.arr[3][6]=4;x.arr[3][7]=1;
        x.arr[4][1]=0;x.arr[4][2]=0;x.arr[4][3]=0;x.arr[4][4]=1;x.arr[4][5]=3;x.arr[4][6]=3;x.arr[4][7]=1;
        x.arr[5][1]=0;x.arr[5][2]=0;x.arr[5][3]=0;x.arr[5][4]=0;x.arr[5][5]=1;x.arr[5][6]=2;x.arr[5][7]=1;
        x.arr[6][1]=0;x.arr[6][2]=0;x.arr[6][3]=0;x.arr[6][4]=0;x.arr[6][5]=0;x.arr[6][6]=1;x.arr[6][7]=1;
        x.arr[7][1]=0;x.arr[7][2]=0;x.arr[7][3]=0;x.arr[7][4]=0;x.arr[7][5]=0;x.arr[7][6]=0;x.arr[7][7]=1;
        y.arr[1][1]=b;
        y.arr[2][1]=a;
        y.arr[3][1]=16;
        y.arr[4][1]=8;
        y.arr[5][1]=4;
        y.arr[6][1]=2;
        y.arr[7][1]=1;
        if(n==1){
            cout<<a<<endl;
        }
        else if(n==2){
            cout<<b<<endl;
        }
        else{
            ans=ksm(x,n-2);
            ans=mul(ans,y);    
            cout<<ans.arr[1][1]<<endl;
        }
    }
    
    return 0;
}
View Code

 

神奇的矩阵快速幂

以上是关于快速幂的主要内容,如果未能解决你的问题,请参考以下文章

矩阵快速幂

快速幂

快速幂

快速幂乘法&快速幂取余

快速幂和慢速乘

快速幂解法