Count
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 708 Accepted Submission(s): 279
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
Source
题解:
矩阵快速幂模板题。
转移矩阵:
1 2 1 0 0 0
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
初始矩阵:
2
1
27
9
3
1
代码:
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn = 1e5+7;
const int mod = 123456789;
const int N = 7;
struct matrix{
ll m[N][N];
void init_0(){
memset(m, 0, sizeof(m));
}
void init_1(){
init_0();//矩阵内容初始化为0
for(int i = 1; i <= N; ++i)m[i][i] = 1;
}
void init(){
init_0();//矩阵内容初始化为0
m[1][1] = 1, m[1][2] = 2, m[1][3] = 1;
m[2][1] = 1;
m[3][3] = 1, m[3][4] = 3, m[3][5] = 3, m[3][6] = 1;
m[4][4] = 1, m[4][5] = 2, m[4][6] = 1;
m[5][5] = 1, m[5][6] = 1;
m[6][6] = 1;
}
matrix operator*(const matrix&M)const{
matrix temp;
temp.init_0();//矩阵内容初始化为0
for(int i = 1; i < N; ++i)
for(int j = 1; j < N; ++j)
for(int k = 1; k < N; ++k)
temp.m[i][j] = (temp.m[i][j] + (m[i][k] * M.m[k][j]%mod))%mod;
return temp;
}
};
matrix qpow(ll n){
matrix ans, p;
ans.init_1();
p.init();
while(n){
if(n&1) ans = ans * p;
p = p * p;
n >>= 1;
}
return ans;
}
int main(){
ll t, n;
ll a[7] = {0,2,1,27,9,3,1};
cin >> t;
while(t--){
cin >> n;
ll ans = 0;
if(n>=3){
matrix b = qpow(n-2);
for(int i = 1; i < N; ++i){
ans = ans%mod + (b.m[1][i]%mod) * (a[i]%mod);
}
cout << ans%mod << endl;
}
else cout << n << endl;
}
return 0;
}