码迷,mamicode.com
首页 > 其他好文 > 详细

快速幂

时间:2019-08-01 17:20:08      阅读:79      评论:0      收藏:0      [点我收藏+]

标签:main   spl   快速   复杂   ==   接下来   recent   second   cli   

普通快速幂:

复杂度 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

 

神奇的矩阵快速幂

快速幂

标签:main   spl   快速   复杂   ==   接下来   recent   second   cli   

原文地址:https://www.cnblogs.com/meanttobe/p/11283841.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!