CF392C Yet Another Number Sequence 题解

显然是一道矩阵加速的题。

发现不好做,不妨推一下式子。

a i = f ( i ) ∗ i k a_i=f(i)*i^k ai=f(i)ik

< = > a i = ( f i − 1 + f i − 2 ) ∗ i k <=> a_i=(f_{i-1}+f_{i-2})*i^k <=>ai=(fi1+fi2)ik

< = > a i = ( f i − 1 ∗ ( i − 1 + 1 ) k + f i − 2 ∗ ( i − 2 + 2 ) k ) <=> a_i=(f_{i-1}*(i-1+1)^k+f_{i-2}*(i-2+2)^k) <=>ai=(fi1(i1+1)k+fi2(i2+2)k)

< = > a i = f i − 1 × ∑ C ( u , k ) × ( i − 1 ) u + f i − 2 × ∑ C ( v , k ) × ( i − 2 ) v × 2 k − v ( 0 ≤ u , v ≤ k ) <=> a_i=f_{i-1}\times \sum{C(u,k)\times (i-1)^u}+f_{i-2}\times\sum{C(v,k)\times (i-2)^v \times 2^{k-v}}(0\leq u,v \leq k) <=>ai=fi1×C(u,k)×(i1)u+fi2×C(v,k)×(i2)v×2kv(0u,vk)

< = > a i = ∑ C ( u , k ) × f i − 1 × ( i − 1 ) u + ∑ C ( v , k ) × f i − 2 × ( i − 2 ) v × 2 k − v ( 0 ≤ u , v ≤ k ) <=> a_i=\sum{C(u,k)\times f_{i-1}\times (i-1)^u}+\sum{C(v,k)\times f_{i-2}\times(i-2)^v \times 2^{k-v}}(0\leq u,v \leq k) <=>ai=C(u,k)×fi1×(i1)u+C(v,k)×fi2×(i2)v×2kv(0u,vk)

关于 f i − 1 ( i − 1 ) u / f i − 2 ( i − 2 ) v f_{i-1}(i-1)^u/f_{i-2}(i-2)^v fi1(i1)u/fi2(i2)v,用二项式定理进行矩阵加速即可。

所以目标矩阵大概是这个样子:

[ f i , f i − 1 , a n s i , f i i 0 , f i i 1 , . . , f i i k , f i − 1 ( i − 1 ) 0 , f i − 1 ( i − 1 ) 1 , . . . , f i − 1 ( i − 1 ) k ] [f_i, f_{i-1}, ans_i, f_ii^0,f_ii^1, .., f_ii^k, f_{i-1}(i-1)^0, f_{i-1}(i-1)^1, ..., f_{i-1}(i-1)^k] [fi,fi1,ansi,fii0,fii1,..,fiik,fi1(i1)0,fi1(i1)1,...,fi1(i1)k]

(具体的转移矩阵请读者自己去推,我懒得打上去了,大概长下面这个样子。。。)

时间复杂度: O ( k 3 l o g 2 ( n ) ) \mathcal{O}(k^3log_2(n)) O(k3log2(n))

Code

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <climits>
#include <cstring>
#define LL long long
using namespace std;
const int MAXN = 100, Mod = 1e9 + 7;
LL n;
int k, C[MAXN][MAXN], cnt, Pow[MAXN], a[MAXN], res;
struct Fuck {
	int s[MAXN][MAXN];
	Fuck() {}
	Fuck(int S[][MAXN]) {
		for(int i = 1; i <= cnt; i ++) for(int j = 1; j <= cnt; j ++) s[i][j] = S[i][j];
	}
	Fuck operator * (const Fuck P) const {
		Fuck ans;
		for(int i = 1; i <= cnt; i ++) for(int j = 1; j <= cnt; j ++) ans.s[i][j] = 0;
		for(int i = 1; i <= cnt; i ++) for(int j = 1; j <= cnt; j ++) for(int u = 1; u <= cnt; u ++) ans.s[i][j] = (ans.s[i][j] + (LL)s[i][u] * P.s[u][j] % Mod) % Mod;
		return ans;
	}
};
Fuck Quick_Pow(Fuck x, LL T) {
	Fuck ans = x;
	for(; T; T >>= 1) {
		if(T & 1) ans = ans * x;
		x = x * x; 
	}
	return ans;
}
int main() {
	Fuck t;
	scanf("%lld%d", &n, &k); Pow[0] = 1; cnt = (k << 1) + 5;
	for(int i = 0; i <= k; i ++) C[0][i] = 1, C[i][i] = 1;
	for(int i = 1; i <= k; i ++) for(int j = i + 1; j <= k; j ++) C[i][j] = (C[i][j - 1] + C[i - 1][j - 1]) % Mod;
	for(int i = 1; i <= k + 1; i ++) Pow[i] = Pow[i - 1] * 2 % Mod;
	if(n == 1) { printf("1"); return 0; }
	if(n == 2) { printf("%d", (Pow[k + 1] + 1) % Mod); return 0; }
	t.s[1][1] = t.s[2][1] = t.s[1][2] = t.s[3][3] = 1;
	for(int i = 4; i <= 4 + k; i ++) t.s[i][3] = C[i - 4][k];
	for(int i = 5 + k; i <= 5 + 2 * k; i ++) t.s[i][3] = (LL)C[i - 5 - k][k] * Pow[5 + 2 * k - i] % Mod;
	for(int i = 4; i <= 4 + k; i ++) {
		for(int j = 4; j <= i; j ++) t.s[j][i] = C[j - 4][i - 4];
		for(int j = k + 5; j <= k + i + 1; j ++) t.s[j][i] = (LL)C[j - k - 5][i - 4] * Pow[k + i + 1 - j] % Mod;
	}
	for(int i = 5 + k; i <= 5 + 2 * k; i ++) t.s[i - k - 1][i] = 1;
	t = Quick_Pow(t, n - 3); a[1] = 2; a[2] = 1; a[3] = ((1LL << (k + 1)) + 1) % Mod;
	for(int i = 4; i <= k + 4; i ++) a[i] = Pow[i - 3];
	for(int i = k + 5; i <= 2 * k + 5; i ++) a[i] = 1;
	for(int i = 1; i <= 2 * k + 5; i ++) res = (res + (LL)a[i] * t.s[i][3] % Mod) % Mod;
	printf("%d", res);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值