【HDU6172】线性递推

1.题目链接。网上很多题解都说是打表找规律,tql。这个题我写了2h多,从推导,到打表。知道最后才发现规律。因为最后的答案要求的是sqrt(an)%mod(mod=1e9+7),所以我分析了半天发现只能是sqrt(an)这个东西存在线性递推公式,队友说也有可能是在n达到一定的值的时候,4^n成为an的主要贡献值,所以开方的主要矛盾就是4^n.最后证明这个想法是错的。an的数量级是没办法用某个部分确定下来的,所以我继续尝试寻找sqrt(an)的线性递推公式,如果找到它,直接使用快速幂解决。然后暴力的高斯消元,数据实在是太大了,解方程都没法解,最后都绝望了,然后观察到hn的递推后边-16,an又加了4的n次方。这是故意的吧,然后就把hb线性递推的系数带进去,完美符合。行吧,也算是解决了。最后看网上的一份比较靠谱的说法是:BM线性递推找规律。行吧,又学到了新东西。也提醒了我,要大胆的猜想。

#include
using namespace std;
typedef long long ll;
struct Sarray 
{
	static const ll LEN = 105;
	static const ll mod = 1e9 + 7;
	ll len, data[LEN][LEN];

	Sarray(ll len, ll flag) :len(len) {
		for (ll i = 0; i < len; i++) {
			for (ll j = 0; j < len; j++)data[i][j] = 0;
			data[i][i] = flag;
		}
	}

	Sarray operator *(const Sarray&a) {
		Sarray tem(a.len, 0);
		for (ll i = 0; i < len; i++) {
			for (ll j = 0; j < len; j++) {
				for (ll k = 0; k < len; k++) {
					tem.data[i][j] = (tem.data[i][j] + data[i][k] * a.data[k][j]) % mod;
				}
			}
		}
		return tem;
	}

	Sarray operator +(const Sarray&a) {
		Sarray tem(a.len, 0);
		for (ll i = 0; i < len; i++) {
			for (ll j = 0; j < len; j++) {
				tem.data[i][j] = (data[i][j] + a.data[i][j]) % mod;
			}
		}
		return tem;
	}

};

Sarray qpow(Sarray a, ll b) {//会更改a,不能按引用传递
	Sarray tem(a.len, 1);
	while (b) {
		if (b & 1)tem = a * tem;
		a = a * a;
		b >>= 1;
	}
	return tem;
}
Sarray sigma(Sarray&p, ll n) 
{
	Sarray E(p.len, 1);
	if (n == 0)return E;
	if (n == 1)return E + p;
	if (n & 1) return (E + qpow(p, n / 2 + 1))*sigma(p, n >> 1);
	else return (E + qpow(p, n / 2 + 1))*sigma(p, n / 2 - 1) + qpow(p, n >> 1);
}
Sarray a(3, 0), org(3, 0), ans_array(3, 0);


int main() {
	a.data[0][0] = 4;
	a.data[0][1] = 17;
	a.data[0][2] = Sarray::mod - 12;
	a.data[1][0] = 1;
	a.data[2][1] = 1;

	org.data[0][0] = 1255;//n=4
	org.data[1][0] = 197;//n=3
	org.data[2][0] = 31;//n=2

	ll ans[5] = { 0,0,31,197,1255 };

	ll T;
	scanf("%lld", &T);
	while (T--) {
		ll n;
		scanf("%lld", &n);
		if (n <= 4) {
			printf("%lld\n", ans[n]);
		}
		else {
			ans_array = qpow(a, n - 4)*org;
			printf("%lld\n", ans_array.data[0][0]);
		}
	}
}

 

你可能感兴趣的:(数学)