CodeChef February Challenge 2018 Broken Clock (三角函数推导 + 矩阵快速幂)

题目链接  Broken Clock   中文题面链接

令$cos(xα) = f(x)$

根据三角函数变换公式有

$f(x) = \frac{2d}{l} f(x-1) - f(x-2)$

我们现在要求的是$l * f(t)$,把$f(t)$表示成$\frac{p}{q}$的形式

令$f(x) = \frac{g(x)}{l^{x}}$,那么$g(x) = p, l^{x} = q$

$\frac{g(x)}{l^{x}} = \frac{2d}{l} * \frac{g(x-1)}{l^{x-1}} - \frac{g(x-2)}{l^{x-2}}$

$g(x) = 2dg(x-1) - l^{2}g(x-2)$

那么这就是一个很显然的矩阵加速的套路,用矩阵快速幂求解$g(t)$即可。

 

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)
#define MP		make_pair
#define fi		first
#define se		second


typedef long long LL;

const LL mod = 1e9 + 7;

struct Matrix{ LL arr[3][3]; } unit, a, c;

LL p, q, d, l, t;
int T, n;

inline LL Pow(LL a, LL b, LL mod){
	LL ret(1);
	for (; b; b >>= 1, (a *= a) %= mod) if (b & 1) (ret *= a) %= mod;
	return ret;
}

Matrix Mul(Matrix a, Matrix b){
	Matrix c;
	rep(i, 1, n) rep(j, 1, n){
		c.arr[i][j] = 0;
		rep(k, 1, n) (c.arr[i][j] += (a.arr[i][k] * b.arr[k][j] % mod)) %= mod;
	}
	return c;
}

Matrix Pow(Matrix a, int k){
	Matrix ret(unit); for (; k; k >>= 1, a = Mul(a, a)) if (k & 1) ret = Mul(ret, a); return ret;
}


int main(){

	n = 2;
	unit.arr[1][1] = unit.arr[2][2] = 1;


	scanf("%d", &T);
	while (T--){
		scanf("%lld%lld%lld", &l, &d, &t);
		q = Pow(l, t, mod);
		c.arr[1][1] = 2 * d % mod;
		c.arr[1][2] = -l * l % mod;
		c.arr[1][2] += mod;
		c.arr[1][2] %= mod;
		c.arr[2][1] = 1;
		c.arr[2][2] = 0;
		--t;
		a = unit;
		while (t){
			if (t & 1) a = Mul(a, c);
			t >>= 1;
			c = Mul(c, c);
		}

		p = (a.arr[1][1] * d % mod + a.arr[1][2] % mod) % mod;
		p %= mod;
		printf("%lld\n", l * p % mod * Pow(q, mod - 2, mod) % mod);
	}

	return 0;
}

 

  

 

posted @ 2018-02-18 18:23  cxhscst2  阅读(305)  评论(0编辑  收藏  举报