【hdu】6470 Count - 矩阵快速幂

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;
} 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值