数学(矩阵快速幂)

 

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

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;
}

题目:http://acm.hdu.edu.cn/showproblem.php?pid=6470

分析:递推式a[i]=a[i-1]+2*a[i-2]+n^3,与上题不同的是有个n三方,这里就要用二项式定理将n^3分解

Ac code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=123456789;
ll f[10]={0,1,2};
ll res[10][10];
ll c[10][10];
void muti(ll a[][10],ll b[][10])
{
	ll tmp[10][10];
	memset(tmp,0,sizeof tmp);
	for(int i=1;i<=6;i++)
	  for(int j=1;j<=6;j++)
	    for(int k=1;k<=6;k++)
	      tmp[i][j]=(tmp[i][j]+a[i][k]*b[k][j]%mod)%mod;
	for(int i=1;i<=6;i++)
	  for(int j=1;j<=6;j++)
	    a[i][j]=tmp[i][j];
}
void Pow(ll n)
{
	memset(res,0,sizeof res);
	memset(c,0,sizeof c);
	for(int i=1;i<=6;i++) res[i][i]=1;
	c[1][1]=c[1][3]=c[1][6]=c[2][1]=c[3][3]=c[3][6]=c[4][4]=c[4][6]=c[5][5]=c[5][6]=c[6][6]=1;
	c[1][2]=c[4][5]=2;
	c[1][4]=c[1][5]=c[3][4]=c[3][5]=3;
	while(n){
		if(n&1)
		  muti(res,c);
		muti(c,c);
		n>>=1;
	}
} 
int main()
{
	int t;
	ll n;
	scanf("%d",&t);
	while(t--){
		scanf("%lld",&n);
		if(n<=2)
		{
			printf("%lld\n",f[n]);
			continue;
		}
		n-=2;
		Pow(n);
		ll ans=(2*res[1][1]%mod+res[1][2]%mod+8*res[1][3]%mod+4*res[1][4]%mod+2*res[1][5]%mod+res[1][6]%mod)%mod;
		printf("%lld\n",ans);
	}
	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;
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值