Problem Description
Farmer John有n头奶牛.
某天奶牛想要数一数有多少头奶牛,以一种特殊的方式:
第一头奶牛为1号,第二头奶牛为2号,第三头奶牛之后,假如当前奶牛是第n头,那么他的编号就是2倍的第n-2头奶牛的编号加上第n-1头奶牛的编号再加上自己当前的n的三次方为自己的编号.
现在Farmer John想知道,第n头奶牛的编号是多少,估计答案会很大,你只要输出答案对于123456789取模.
Input
第一行输入一个T,表示有T组样例
接下来T行,每行有一个正整数n,表示有n头奶牛 (n>=3)
其中,T=10^4,n<=10^18
Output
共T行,每行一个正整数表示所求的答案
Sample Input
5 3 6 9 12 15
Sample Output
31 700 7486 64651 527023
根据题目条件,易知递推公式:,但是由于题给数据特别巨大,所以不能用数组和简单for循环递推来完成这个目标。
所以就有另一种办法——矩阵代数,利用矩阵之间的乘积关系来表达出这个式子,并且结果矩阵中必定含有所求项(在这里是A(n))。不过我们现在除了知道思路的大方向之外什么都不知道,解决这个问题需要攻破两个点:
首先,依据下表(盗的图)来解决第一个问题。
第一个问题的答案在表中很明显,所谓第A(n)项就是一个特殊矩阵的幂和原矩阵的乘积。
用矩阵解决递推问题的这种思路是怎么得出来的我不知道,但是可以从上表知道一件事情来解决第二个问题:
通过把代表原递推式A(n-1)的矩阵乘以一个X矩阵或者X向量就可以得到代表递推式第A(n)项的矩阵,简而言之,这是一个矩阵方程,而未知量X即是我们的“特殊矩阵”的表达式。
令人欣喜的是,另外两项也是有规律可循的——A(n-1)矩阵中包含递推项A(n-1)与A(n-2)以及递推式常数(n)从其给定幂次到0次幂(也就是常数1)的罗列,由于这个矩阵是用来求第n项的,所以A(n-1)项的矩阵里的常数是n.右侧A(n)矩阵就是把左侧A(n-1)矩阵里的递推项下标和常数加上1即可。
详情可见上表的递推式。
而初始矩阵就更好求了,就是把题目中的初始数据依次代入即可。
那么就可以得到这样的两个重要式子:
1.
2.初始矩阵:{2,1,27,9,3,1}(6 x 1矩阵)(若方程求解有问题,欢迎小窗提问)
用实现这样的操作还需要模拟矩阵乘法,在此不作赘述。
综上所述,可以得到这样的思路
利用模拟的矩阵乘法和矩阵幂乘,解决问题。
代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#define DETERMINATION main
#define lldin(a) scanf("%lld",&a)
#define din(a) scanf("%d",&a)
#define printlnlld(a) printf("%lld\n",a)
#define printlnd(a) printf("%d\n",a)
#define printlld(a) printf("%lld",a)
#define printd(a) printf("%d",a)
#define reset(a,b) memset(a,b,sizeof(a))
const int INF=0x3f3f3f3f;
using namespace std;
const double PI=acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod=123456789;
///Schlacht von Stalingrad
/**Although there will be many obstructs ahead,
the desire for victory still fills you with determination..**/
struct matrix//为了避免传参,把表示矩阵的二维数组塞进结构体里
{
ll mat[8][8];
ll row,col;
};
matrix multiplication(matrix a,matrix b)//根据行列规则模拟的矩阵乘法
{
matrix tmp;
reset(tmp.mat,0);
tmp.row=a.row;
tmp.col=b.col;
if(a.col==b.row)
{
for(int i=1; i<=a.row; i++)
{
for(int j=1; j<=b.col; j++)
for(int k=1; k<=a.col; k++)
{
tmp.mat[i][j]+=(a.mat[i][k]*b.mat[k][j])%mod;
tmp.mat[i][j]%=mod;
}
}
}
return tmp;
}
matrix quick_power(matrix a,ll n)
{
matrix identity;//单位矩阵的定义与初始化
reset(identity.mat,0);
identity.col=6;
identity.row=6;
for(int i=1; i<=6; i++)
for(int j=1; j<=6; j++)
{
if(i==j)
identity.mat[i][j]=1;
else
identity.mat[i][j]=0;
}
while(n)//快速幂
{
if(n&1)
identity=multiplication(identity,a);
n>>=1;
a=multiplication(a,a);
}
// for(int i=1; i<=identity.row; i++)
// {
// for(int j=1; j<=identity.col; j++)
// cout<>t;
initialization();
while(t--)
{
ll n;
cin>>n;
matrix ans,rmp;
ans=quick_power(ILETS,n-2);
rmp=multiplication(ans,initialed);
// for(int i=1;i<=6;i++)
// cout<