数学(矩阵快速幂)

 

今天刚学了矩阵快速幂,所以忍不住想贴个板子哈哈哈......(菜鸟的乐点真的很低)

Read the program below carefully then answer the question. 
#pragma comment(linker, "/STACK:1024000000,1024000000") 
#include <cstdio> 
#include<iostream> 
#include <cstring> 
#include <cmath> 
#include <algorithm> 
#include<vector> 

const int MAX=100000*2; 
const int INF=1e9; 

int main() 

  int n,m,ans,i; 
  while(scanf("%d%d",&n,&m)!=EOF) 
  { 
    ans=0; 
    for(i=1;i<=n;i++) 
    { 
      if(i&1)ans=(ans*2+1)%m; 
      else ans=ans*2%m; 
    } 
    printf("%d\n",ans); 
  } 
  return 0; 
}

Input

Multi test cases,each line will contain two integers n and m. Process to end of file. 
[Technical Specification] 
1<=n, m <= 1000000000

Output

For each case,output an integer,represents the output of above program.

Sample Input

1 10
3 100

Sample Output

1
5

题解:很容易可得递推式f[n]=2*f[n-2]+f[n-1]+1,但n很大,开不了这么大的数组,所以可以用矩阵快速幂

AC代码:

#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
ll a[4][4];
ll temp[4][4];
ll n,m;
ll res[4][4];
int ans[7]={0,1,2,5,10,21,42};
void muti(ll a[][4],ll b[][4])
{
    memset(temp,0,sizeof temp);
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
          for(int k=1;k<=3;k++)
            temp[i][j]+=(a[i][k]*b[k][j])%m;
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
          a[i][j]=temp[i][j];
}
void Pow()
{
    memset(res,0,sizeof res);
    for(int i=1;i<=3;i++)
        res[i][i]=1;
    memset(a,0,sizeof a);
    a[1][2]=2;
    a[2][1]=a[2][2]=a[3][2]=a[3][3]=1;
    while(n)
    {
        if(n&1)
            muti(res,a);
        muti(a,a);
        n>>=1;
    }
}
int main()
{
    while(cin>>n>>m)
    {
        if(n<=2)
        {
            cout<<ans[n]%m<<endl;
            continue;
        }
        else
        {
            n-=2;
            Pow();
            cout<<(res[1][2]%m+2*res[2][2]%m+res[3][2]%m)%m<<endl;
        }
    }
    return 0;
}

板子:

const int N=10;
int tmp[N][N];
void multi(int a[][N],int b[][N],int n)
{
    memset(tmp,0,sizeof tmp);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        for(int k=1;k<=n;k++)
        tmp[i][j]+=a[i][k]*b[k][j];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        a[i][j]=tmp[i][j];
}
int res[N][N];
void Pow(int a[][N],int n)
{
    memset(res,0,sizeof res);
    for(int i=1;i<=n;i++) res[i][i]=1;
    while(n)
    {
        if(n&1)
            multi(res,a,n);//res=res*a;复制直接在multi里面实现了;
        multi(a,a,n);//a=a*a
        n>>=1;
    }
}

猜你喜欢

转载自blog.csdn.net/shaohang_/article/details/81370016
今日推荐