CountTime Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 370 Accepted Submission(s): 148 Problem Description Farmer John有n头奶牛. Input 第一行输入一个T,表示有T组样例 Output 共T行,每行一个正整数表示所求的答案 Sample Input
5 3 6 9 12 15
扫描二维码关注公众号,回复:
5570363 查看本文章
Sample Output
31 700 7486 64651 527023 Source Recommend liuyiding | We have carefully selected several similar problems for you: 6470 6469 6468 6467 6466 |
做这题之前有个题跟 这题极其类似:
F(n) = F(n-1) + 2F(n-2) + n^4
具体解法在这
https://www.jianshu.com/p/25eba927d9da
以上内容来自 https://www.jianshu.com/p/25eba927d9da
/*
我们把解决这类题目的过程分解为如下步骤:
1. 把非线性递推式转化为线性递推式(线性递推式可忽略第一步)
2. 根据线性递推式得到F(n)和F(n+1)的矩阵序列
3. 根据F(n)和F(n+1)的矩阵序列得到中间的转移矩阵
4. 根据转移矩阵编写代码
分步拆解问题
首先把非线性递推式转换为线性递推式
∵ (n+1)4 = n4 + 4n3 + 6n2 + 4n + n0
∵ F(n+1) = F(n) + 2F(n-1) + (n+1)4
∴ F(n+1) = F(n) + 2F(n-1) + n4 + 4n3 + 6n2 + 4n + n0
然后我们看下下面的状态转移矩阵
图有误,等号左边两个矩阵位置换一下
图(1)
左边的矩阵表示F(n)
项的矩阵,右边的矩阵表示F(n+1)
项的矩阵。而中间的A矩阵就是需要求的转移矩阵。图(1)
左边的矩阵怎么得到?我们看刚才得到的递归式
F(n+1) = F(n) + 2F(n-1) + n4 + 4n3 + 6n2 + 4n + n0
我们把F(n)
放在矩阵顶部,表示第n项的值,然后剩下的元素F(n-1)
、 n4、n3、n2、n、 n0 ,去掉系数后与F(n)
一起构成一个矩阵。同理,F(n+1)
的矩阵也是F(n+1)
在顶部,表示第n+1项的值,然后剩下的元素F(n)
、 (n+1)4、(n+1)3、(n+1)2、(n+1)、 (n+1)0 去掉系数后与F(n+1)
构成一个矩阵。
好,我们现在得到了F(n)
和F(n+1)
的矩阵,那怎么求转移过去的矩阵A呢?首先,A是一个7×7的矩阵,且根据矩阵相乘规则,可以得到矩阵A,如下图(如果对矩阵相乘不熟悉的可以先看一下矩阵相乘哈)
图有误,等号左边两个矩阵位置换一下
好了,到现在为止,得到了图(2)
的转移矩阵后,我们解决了前三步,还剩最后一步。怎么把这个转移矩阵应用到代码里面呢?
题中给出了F(1) = a,F(2) = b
所以F(3) = 2a + b + 34 = 2a + b + 24 + 4×23 + 6×22 + 4×21 + 20
图(3)
作者:徐森威
链接:https://www.jianshu.com/p/25eba927d9da
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
*/
这里是F[n]=F[n-1]+2F[n-2]+n^3;
看完解法是不是感觉很妙,好我们就依葫芦画瓢,写这个题。将(n+1)^3拆分就是n^3+3*n^2+3*n+n^0;
上图,
===[A]* ,然后通过简单的构造可以得出目的矩阵A=
再套用矩阵快速幂的模板即可~~~~~~~~~~~~~~~AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=6;
const ll mod=123456789;
struct Matrix
{
ll mat[MAXN][MAXN];
Matrix() {}
Matrix operator*(Matrix const &b)const
{
Matrix res;
memset(res.mat, 0, sizeof(res.mat));
for (int i = 0 ;i < MAXN; i++)
for (int j = 0; j < MAXN; j++)
for (int k = 0; k < MAXN; k++)
res.mat[i][j] = (res.mat[i][j]+this->mat[i][k] * b.mat[k][j])%mod;
return res;
}
};
Matrix pow_mod(Matrix base, ll n)
{
Matrix res;
memset(res.mat, 0, sizeof(res.mat));
for (int i = 0; i < MAXN; i++)
res.mat[i][i] = 1;
while (n > 0)
{
if (n & 1) res = res*base;
base = base*base;
n >>= 1;
}
return res;
}
Matrix base,fi;
void init()
{
base.mat[0][0]=1;
base.mat[0][1]=2;
base.mat[0][2]=1;
base.mat[0][3]=3;
base.mat[0][4]=3;
base.mat[0][5]=1;
base.mat[1][0]=1;
base.mat[2][2]=1;
base.mat[2][3]=3;
base.mat[2][4]=3;
base.mat[2][5]=1;
base.mat[3][3]=1;
base.mat[3][4]=2;
base.mat[3][5]=1;
base.mat[4][4]=1;
base.mat[4][5]=1;
base.mat[5][5]=1;
fi.mat[0][0]=2;
fi.mat[1][0]=1;
fi.mat[2][0]=8;
fi.mat[3][0]=4;
fi.mat[4][0]=2;
fi.mat[5][0]=1;
}
int main()
{
init();
int t;
ll n;
cin>>t;
while (t--)
{
scanf("%lld", &n);
if(n<=2)
{
printf("%d\n",n);
continue;
}
Matrix ans = pow_mod(base, n-2);
ans=ans*fi;
printf("%lld\n", ans.mat[0][0]);
}
return 0;
}