快速矩阵的好题
题目描述 :
解题思路:
1.首先,提取问题:
已知,
求
2.代公式:
3.化位矩阵:
矩阵A的构造过程:
第一行不多说。
第二行需要将矩阵中的
变为
,倒着往回推:
第三行需要将变为
,同样,倒着往回推:
第四行将变为
。
4.得到A和X矩阵后,还需要找到初始X矩阵和A的次幂关系。
因为已知,所以从
开始计算,所以n最小为2。此时初始矩阵
为:
此时矩阵A应该是1次幂,所以得到最终公式:
AC代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
typedef long long int ll;
const ll mod = 10007;
const int MAX_N = 4;
ll A[MAX_N][MAX_N],res[MAX_N][MAX_N];
ll temp[MAX_N][MAX_N];
inline void init(ll x,ll y)
{
memset(A,0,sizeof(A));
A[0][0] = 1;A[0][1] = ((x%mod)*(x%mod))%mod;A[0][2] = (2*(x%mod)*(y%mod))%mod;A[0][3] = ((y%mod)*(y%mod))%mod;
A[1][0] = 0;A[1][1] = ((x%mod)*(x%mod))%mod;A[1][2] = (2*(x%mod)*(y%mod))%mod;A[1][3] = ((y%mod)*(y%mod))%mod;
A[2][1] = x%mod; A[2][2] = y%mod;
A[3][1] = 1;
}
//A = A*B
void MXMP(ll a[][MAX_N],ll b[][MAX_N],ll n)
{
//重置临时矩阵temp
for(int i = 0;i<n;i++)
for(int j = 0;j<n;j++)
temp[i][j] = 0;
for(int i = 0;i<n;i++)
for(int j = 0;j<n;j++)
for(int k = 0;k<n;k++)
temp[i][j] = (temp[i][j] + (a[i][k]*b[k][j])%mod)%mod;//防止超界
for(int i = 0;i<n;i++)
for(int j = 0;j<n;j++)
a[i][j] = temp[i][j];
}
//A = A**x
void PowerMod(ll A[][MAX_N],ll n,ll x)//x为次幂,n为矩阵行/列
{
memset(res,0,sizeof(res));
for(int i = 0;i<n;i++) res[i][i] = 1;//初始化为单位矩阵
while(x){
if(x&1) MXMP(res,A,n);
MXMP(A,A,n);
x >>= 1;
}
for(int i = 0;i<n;i++)
for(int j = 0;j<n;j++)
A[i][j] = res[i][j];
}
ll getAns(ll n,ll x,ll y){
if(n == 0) return 1;
if(n == 1) return 2;
init(x,y);
PowerMod(A,MAX_N,n-1);
ll ans = ((A[0][0]%mod)*2)%mod;
ans = (ans+((A[0][1]%mod)*1%mod))%mod;
ans = (ans+((A[0][2]%mod)*1%mod))%mod;
ans = (ans+((A[0][3]%mod)*1%mod))%mod;
return ans;
}
int main()
{
ll n,x,y;
while(scanf("%lld %lld %lld",&n,&x,&y)!= EOF){
ll ans = getAns(n,x,y);
printf("%lld\n",ans%mod);
}
return 0;
}