Count
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
矩阵快速幂的模板题,题目已经给出公式An=An-1+2(An-1)+n*n*n ,然后构造这道题的矩阵就可以了
因为这个道题的矩阵的维数有些多,构造可能没有那么简单所以我们先过一遍斐波那契的矩阵
An=An-1+An-2
所以斐波那契构造的矩阵为
然后这道题目也是一样,主要需要构成n*n*n
通过以上构造的矩阵为:(矩阵可能不同,最后算答案的时候计算公式也不同)
第一部分 第二部分 第三部分
矩阵就给出来了,然后直接上代码
#include<bits/stdc++.h>
using namespace std;
struct node{
long long m[6][6];
}res,A;
const int M=123456789;
node mul(node x,node y)
{
node v;
memset(v.m,0,sizeof(v.m));
for(int i=0;i<6;i++)
for(int j=0;j<6;j++)
for(int k=0;k<6;k++)
{
v.m[i][j]+=x.m[i][k]*y.m[k][j];
v.m[i][j]=(v.m[i][j]+M)%M;//一定要记得先加M
}
return v;
}
node ful(node x,long long n)//快速幂内容
{
memset(res.m,0,sizeof res.m);
for(int i=0;i<6;i++) res.m[i][i]=1;
while(n)
{
if(n&1) res=mul(res,x);
x=mul(x,x);
n>>=1;
}
return res;
}
int main()
{
A={ 1,2,1,3,3,1,
1,0,0,0,0,0,
0,0,1,3,3,1,
0,0,0,1,2,1,
0,0,0,0,1,1,
0,0,0,0,0,1
};
int t;
scanf("%d",&t);
while(t--)
{
long long n;
scanf("%lld",&n);
if(n<3) printf("%lld\n",n);
else{
node v=ful(A,n-2);
long long ccc=v.m[0][0]*2+v.m[0][1]*1+v.m[0][2]*8+v.m[0][3]*4+v.m[0][4]*2+v.m[0][5];
//矩阵从n=3开始,然后带入第二部分的值,例如A3-1=2,A2-1=1,(3-1)^3=8,(3-1)^2=4
ccc%=M;
printf("%lld\n",ccc);
}
}
}