矩阵优化学习记录1

洛谷 P3390 【模板】矩阵快速幂

矩阵快速幂,作为学习矩阵优化的前置知识
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=105,MOD=1e9+7;
int n,k;
struct number{int num[N][N];}base,ans;

inline number mul(number a,number b)
{
	number c;
	for (register int i=1; i<=n; ++i)
	for (register int j=1; j<=n; ++j) c.num[i][j]=0;
	for (register int i=1; i<=n; ++i)
	for (register int j=1; j<=n; ++j)
	for (register int k=1; k<=n; ++k)
	c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j]%MOD)%MOD;
	return c;
}

inline void pow(int k)
{
	while (k)
	{
		if (k&1ll) ans=mul(ans,base);
		base=mul(base,base);
		k>>=1ll;
	}
}

signed main(){
	scanf("%lld%lld",&n,&k);
	for (register int i=1; i<=n; ++i)
	for (register int j=1; j<=n; ++j) scanf("%lld",&base.num[i][j]); 
	
	for (register int i=1; i<=n; ++i) ans.num[i][i]=1;
	
	pow(k);
	
	for (register int i=1; i<=n; ++i)
	{
		for (register int j=1; j<=n; ++j) printf("%lld ",ans.num[i][j]);
		puts("");
	}
return 0;	
}

洛谷 P1962 斐波那契数列

最基础的矩阵优化题
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MOD=1e9+7;
int n;
struct number{int num[5][5];}base,ans,b;

inline number mul(number a,number b)
{
	number c;
	for (register int i=1; i<=2; ++i)
	for (register int j=1; j<=2; ++j) c.num[i][j]=0;
	for (register int i=1; i<=2; ++i)
	for (register int j=1; j<=2; ++j)
	for (register int k=1; k<=2; ++k)
	c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j]%MOD)%MOD;
	return c;	
}

inline void pow(int k)
{
	while (k)
	{
		if (k&1ll) ans=mul(ans,base);
		base=mul(base,base);
		k>>=1ll;
	}
}

signed main(){
	scanf("%lld",&n);
	if (n<2) 
	{
		puts("1");
		return 0;
	}
	base.num[1][1]=base.num[1][2]=base.num[2][1]=1;
	for (register int i=1; i<=2; ++i) ans.num[i][i]=1;
	pow(n-2);
	b.num[1][1]=b.num[2][1]=1;
	ans=mul(ans,b); 
	printf("%lld\n",ans.num[1][1]);
return 0;	
}

洛谷 P1306 斐波那契公约数

通过打表发现 gcd(f[n],f[m])=f[gcd(n,m)] ,然后就是上一题了
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,m;
const int MOD=1e8;

int gcd(int a,int b)
{
	if (a%b==0) return b;
	return gcd(b,a%b);
}

struct number{int num[5][5];}base,ans,b;

inline number mul(number a,number b)
{
	number c;
	for (register int i=1; i<=2; ++i)
	for (register int j=1; j<=2; ++j) c.num[i][j]=0;
	for (register int i=1; i<=2; ++i)
	for (register int j=1; j<=2; ++j)
	for (register int k=1; k<=2; ++k)
	c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j]%MOD)%MOD;
	return c;
}

inline void pow(int k)
{
	while (k)
	{
		if (k&1ll) ans=mul(ans,base);
		base=mul(base,base);
		k>>=1ll;
	}
}

signed main(){
	scanf("%lld%lld",&n,&m);
	n=gcd(n,m);
	if (n<2)
	{
		puts("1");
		return 0;
	}
	base.num[1][1]=base.num[1][2]=base.num[2][1]=1;
	for (register int i=1; i<=2; ++i) ans.num[i][i]=1;
	pow(n-2);
	b.num[1][1]=b.num[2][1]=1;
	ans=mul(ans,b); 
	printf("%lld\n",ans.num[1][1]);
return 0;	
}

洛谷 P1939 【模板】矩阵加速(数列)

改变一下公式就可以了
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MOD=1e9+7;
int T,n;
struct number{int num[5][5];}base,ans,b;

inline number mul(number a,number b)
{
	number c;
	for (register int i=1; i<=3; ++i)
	for (register int j=1; j<=3; ++j) c.num[i][j]=0;
	for (register int i=1; i<=3; ++i)
	for (register int j=1; j<=3; ++j)
	for (register int k=1; k<=3; ++k)
	c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j]%MOD)%MOD; 
	return c;
}

inline void pow(int k)
{
	while (k)
	{
		if (k&1ll) ans=mul(ans,base);
		base=mul(base,base);
		k>>=1ll;
	}
}

signed main(){
	scanf("%lld",&T);
	while (T--)
	{
		memset(base.num,0,sizeof(base.num));
		memset(ans.num,0,sizeof(ans.num));
		memset(b.num,0,sizeof(b.num));
		scanf("%lld",&n);
		if (n<3)
		{
			puts("1");
			continue;
		}
		base.num[1][1]=base.num[1][3]=base.num[2][1]=base.num[3][2]=1;
		for (register int i=1; i<=3; ++i) ans.num[i][i]=1;
		pow(n-3);
		b.num[1][1]=b.num[2][1]=b.num[3][1]=1;
		ans=mul(ans,b);
		printf("%lld\n",ans.num[1][1]);
	}
return 0;	
}

洛谷 P1349 广义斐波那契数列

把初始矩阵改变一下即可
#include <bits/stdc++.h>
#define int long long
using namespace std;
int p,q,a1,a2,n,MOD;

struct number{int num[5][5];}base,ans,b;

inline number mul(number a,number b)
{
	number c;
	for (register int i=1; i<=2; ++i)
	for (register int j=1; j<=2; ++j) c.num[i][j]=0;
	for (register int i=1; i<=2; ++i)
	for (register int j=1; j<=2; ++j)
	for (register int k=1; k<=2; ++k) 
	c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j]%MOD)%MOD;
	return c;
}

inline void pow(int k)
{
	while (k)
	{
		if (k&1ll) ans=mul(ans,base);
		base=mul(base,base);
		k>>=1ll;
	}
}

signed main(){
	scanf("%lld%lld%lld%lld%lld%lld",&p,&q,&a1,&a2,&n,&MOD);
	if (n<2)
	{
		printf("%lld\n",a1);
		return 0;
	}
	base.num[1][1]=p; base.num[1][2]=q; base.num[2][1]=1;
	for (register int i=1; i<=2; ++i) ans.num[i][i]=1;
	pow(n-2);
	b.num[1][1]=a2; b.num[2][1]=a1;
	ans=mul(ans,b);
	printf("%lld\n",ans.num[1][1]);
return 0;
}
发布了64 篇原创文章 · 获赞 29 · 访问量 701

猜你喜欢

转载自blog.csdn.net/Dove_xyh/article/details/103327698