NYOJ301 递推求值(矩阵快速幂)
2017-04-12 21:51
295 查看
题目:
时间限制:1000 ms | 内存限制:65535 KB
难度:4
描述
给你一个递推公式:
f(x)=a*f(x-2)+b*f(x-1)+c
并给你f(1),f(2)的值,请求出f(n)的值,由于f(n)的值可能过大,求出f(n)对1000007取模后的值。
注意:-1对3取模后等于2
输入第一行是一个整数T,表示测试数据的组数(T<=10000)
随后每行有六个整数,分别表示f(1),f(2),a,b,c,n的值。
其中0<=f(1),f(2)<100,-100<=a,b,c<=100,1<=n<=100000000 (10^9)
输出输出f(n)对1000007取模后的值
样例输入
样例输出
来源经典题目
上传者张云聪
这是一道矩阵快速幂的入门加模板题
矩阵快速幂:
1:思想
矩阵快速幂的思想就是跟数的快速幂一样,假如我们要求2^11,次方,我们可以把 11 写成 1+2+8 ,也就是2^0 + 2^1 + 2^3 。那么把一个O(n)的时间复杂度降到了log(n)
矩阵快速幂的思想和数的快速幂是一模一样的,就是要自己实现矩阵的乘法,然后可以套数的快速幂的模板。
2:难点
矩阵题目的难点在于构造矩阵,一般用于有能够推出递推式的题目,推出递推式之后,发现递推O(n)的复杂度时间比较大,那么我们可以构造一个矩阵,然后用矩阵快速幂降低到log(n)的时间复杂度
代码:
2017/10/10重做代码:
#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#include<iostream>
#include<stack>
#include<queue>
#include<vector>
#include<algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
#define mod 1000007
#define debug() puts("what the fuck!!!")
#define ll long long
using namespace std;
const ll N=3;
struct Matrix
{
ll a
;
Matrix()
{
mem(a,0);
}
void init()
{
mem(a,0);
for(ll i=0; i<N; i++)
a[i][i]=1;
}
};
void print(Matrix a)
{
for(ll i=0; i<N; i++)
{
for(ll j=0; j<N; j++)
printf("%d ",a.a[i][j]);
puts("");
}
}
Matrix mul(Matrix a,Matrix b)
{
Matrix ans;
for(ll i=0; i<N; i++)
for(ll j=0; j<N; j++)
for(ll k=0; k<N; k++)
{
ans.a[i][j]=(ans.a[i][j]%mod+a.a[i][k]*b.a[k][j]%mod)%mod;
}
return ans;
}
Matrix mat_pow(Matrix a,ll n)
{
Matrix ans;
ans.init();
while(n)
{
if(n&1)
ans=mul(ans,a);
a=mul(a,a);
n>>=1;
}
return ans;
}
int main()
{
ll f1,f2,a,b,c,n,t;
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld%lld%lld%lld%lld",&f1,&f2,&a,&b,&c,&n);
if(n==1)
printf("%lld\n",(f1+mod)%mod);
else if(n==2)
printf("%lld\n",(f2+mod)%mod);
else
{
Matrix A;
A.a[0][0]=b,A.a[1][0]=a,A.a[2][0]=c;
A.a[0][1]=A.a[2][2]=1;
Matrix p=mat_pow(A,n-2);
Matrix B;
B.a[0][0]=f2,B.a[0][1]=f1;
B.a[0][2]=1;
Matrix ans=mul(B,p);
printf("%lld\n",(ans.a[0][0]+mod)%mod);
}
}
return 0;
}
递推求值
时间限制:1000 ms | 内存限制:65535 KB难度:4
描述
给你一个递推公式:
f(x)=a*f(x-2)+b*f(x-1)+c
并给你f(1),f(2)的值,请求出f(n)的值,由于f(n)的值可能过大,求出f(n)对1000007取模后的值。
注意:-1对3取模后等于2
输入第一行是一个整数T,表示测试数据的组数(T<=10000)
随后每行有六个整数,分别表示f(1),f(2),a,b,c,n的值。
其中0<=f(1),f(2)<100,-100<=a,b,c<=100,1<=n<=100000000 (10^9)
输出输出f(n)对1000007取模后的值
样例输入
2 1 1 1 1 0 5 1 1 -1 -10 -100 3
样例输出
5 999896 4000
来源经典题目
上传者张云聪
这是一道矩阵快速幂的入门加模板题
矩阵快速幂:
1:思想
矩阵快速幂的思想就是跟数的快速幂一样,假如我们要求2^11,次方,我们可以把 11 写成 1+2+8 ,也就是2^0 + 2^1 + 2^3 。那么把一个O(n)的时间复杂度降到了log(n)
矩阵快速幂的思想和数的快速幂是一模一样的,就是要自己实现矩阵的乘法,然后可以套数的快速幂的模板。
2:难点
矩阵题目的难点在于构造矩阵,一般用于有能够推出递推式的题目,推出递推式之后,发现递推O(n)的复杂度时间比较大,那么我们可以构造一个矩阵,然后用矩阵快速幂降低到log(n)的时间复杂度
代码:
#include <cstdio> #include <cstring> #include <cctype> #include <string> #include <set> #include <iostream> #include <stack> #include <cmath> #include <queue> #include <vector> #include <algorithm> #define mem(a,b) memset(a,b,sizeof(a)) #define inf 0x3f3f3f3f #define mod 1000007 #define N 3 #define M 1000000+10 #define ll long long using namespace std; struct Matrix { ll mat ; }; Matrix unit_matrix= { 1,0,0, 0,1,0, 0,0,1 };//单位矩阵 Matrix mul(Matrix a,Matrix b)//矩阵相乘 { Matrix res; for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) { res.mat[i][j]=0; for(int k=0; k<N; ++k) res.mat[i][j]=(res.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod; } return res; } Matrix pow_matrix(Matrix a,ll n)//矩阵快速幂 { Matrix res=unit_matrix; while(n) { if(n&1) res=mul(res,a); a=mul(a,a); n>>=1; } return res; } int main() { ll t,f1,f2,a,b,c,n; Matrix tmp,arr; scanf("%lld",&t); while(t--) { scanf("%lld%lld%lld%lld%lld%lld",&f1,&f2,&a,&b,&c,&n); if(n==1) printf("%lld\n",(f1+mod)%mod); else if(n==2) printf("%lld\n",(f2+mod)%mod); else { mem(arr.mat,0); mem(tmp.mat,0); arr.mat[0][0]=f2,arr.mat[0][1]=f1,arr.mat[0][2]=1;//构造初始矩阵 tmp.mat[0][0]=b,tmp.mat[1][0]=a,tmp.mat[2][0]=c; tmp.mat[0][1]=tmp.mat[2][2]=1; Matrix p=pow_matrix(tmp,n-2); p=mul(arr,p);//注意p和arr不要写反了 ll ans=(p.mat[0][0]+mod)%mod; printf("%lld\n",ans); } } return 0; }
2017/10/10重做代码:
#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#include<iostream>
#include<stack>
#include<queue>
#include<vector>
#include<algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
#define mod 1000007
#define debug() puts("what the fuck!!!")
#define ll long long
using namespace std;
const ll N=3;
struct Matrix
{
ll a
;
Matrix()
{
mem(a,0);
}
void init()
{
mem(a,0);
for(ll i=0; i<N; i++)
a[i][i]=1;
}
};
void print(Matrix a)
{
for(ll i=0; i<N; i++)
{
for(ll j=0; j<N; j++)
printf("%d ",a.a[i][j]);
puts("");
}
}
Matrix mul(Matrix a,Matrix b)
{
Matrix ans;
for(ll i=0; i<N; i++)
for(ll j=0; j<N; j++)
for(ll k=0; k<N; k++)
{
ans.a[i][j]=(ans.a[i][j]%mod+a.a[i][k]*b.a[k][j]%mod)%mod;
}
return ans;
}
Matrix mat_pow(Matrix a,ll n)
{
Matrix ans;
ans.init();
while(n)
{
if(n&1)
ans=mul(ans,a);
a=mul(a,a);
n>>=1;
}
return ans;
}
int main()
{
ll f1,f2,a,b,c,n,t;
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld%lld%lld%lld%lld",&f1,&f2,&a,&b,&c,&n);
if(n==1)
printf("%lld\n",(f1+mod)%mod);
else if(n==2)
printf("%lld\n",(f2+mod)%mod);
else
{
Matrix A;
A.a[0][0]=b,A.a[1][0]=a,A.a[2][0]=c;
A.a[0][1]=A.a[2][2]=1;
Matrix p=mat_pow(A,n-2);
Matrix B;
B.a[0][0]=f2,B.a[0][1]=f1;
B.a[0][2]=1;
Matrix ans=mul(B,p);
printf("%lld\n",(ans.a[0][0]+mod)%mod);
}
}
return 0;
}
相关文章推荐
- nyoj 301 递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)
- 【矩阵快速幂*模板】nyoj 301 递推求值
- nyoj 301 递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)
- NYOJ——301递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)
- nyoj--301 递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)
- NYOJ 301 递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)
- nyoj 301递推求值(矩阵快速幂的递推求值)
- nyoj301 递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)
- nyoj 301 递推求值(矩阵快速幂)