u's的影响力 (矩阵构造)(第五次重新来过)

我昨天写这个题,写道凌晨两点,一直81分,直到刚才,我发现了错误的地方,一改就A了,woc,心态崩了

μ’s在九人齐心协力下,影响力越来越大了!
已知第一天影响力为 xx ,第二天影响力为 yy ,从第三天开始,每一天的影响力为前两天影响力的乘积再乘以 aabb 次方。 用数学语言描述是:

设第ii天的影响力为f(i)f(i),那么f(1)=xf(1)=xf(2)=yf(2)=y,对于i>2,f(i)=f(i1)f(i2)abi>2,f(i)=f(i-1)*f(i-2)*a^b, 她们想知道第nn天影响力是多少?

由于这个数可能非常大,只需要输出其对 10000000071000000007 取模的值就可以了。

输入:一行五个正整数:n,x,y,a,bn,x,y,a,b(1n,x,y,a,b1012)(1\leq n,x,y,a,b\leq 10^{12})

输出:第nn天的影响力对 10000000071000000007 取模的值。

xxyy 的幂次是叠加的,因为是幂的乘积嘛,而且是f(i)=f(i1)f(i2)f(i)=f(i-1)*f(i-2),可以发现,指数其实就是g(i)=g(i1)+g(i2)g(i)=g(i-1)+g(i-2),其实就是Fib了,求斐波那契数列,xxyy 指数就得到了解决。而对于 aa 的指数,可以明了 bb 是不变的,所以只有 bb 前面的系数在变化,而 bb 前面的系数是当前项 xxyy 的系数之和1-1,因此 bb 的系数也得到了解决。

因为数据量很大,所以不能通过递推求Fib,可以通过矩阵快速幂求解Fib,但是Fib很大,需要取模,而Fib又在指数位置上,根据费马小定理(或者欧拉降幂公式),让Fib对(109+7110^9+7-1)取模即可。

注意n=1n=2n=1||n=2的时候直接输出xyx||y但是,因为xyx||y的值都很大,答案需要对109+710^9 +7取模。(我就这个地方wa了好多好多遍)

#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof a)
const int mod = 1e9 + 7;
typedef long long ll;
ll qc(ll x,ll y,ll m)
{
    return (x*y-(ll)((long double)x/m*y)*m+m)%m;
}
ll qpow(ll x, ll y, ll m){
	ll res = 1;
	res %= m;
	while (y){
		if(y & 1){
			res = qc(res, x, m);
		}
		y >>= 1;
		x = qc(x, x, m);
	}
	return res % m;
}
struct p{
	ll a[3][3];
	p(){
		mem(a, 0);
	}
	void clear(){
		p();
	}
	p(ll b[3][3]){
		clear();
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				a[i][j] = b[i][j];
	}
	p operator * (const p& temp){
		p ans;
		ans.clear();
		for (int i = 1; i <= 2; i++){
			for (int j = 1; j <= 2; j++){
				for (int k = 1; k <= 2; k++){
					ans.a[i][j] += qc(this->a[i][k], temp.a[k][j], mod - 1);
					ans.a[i][j] %= (mod - 1);
				}
			}
		}
		return ans;
	}
};
p qpow(p t, ll n){
	p res;
	res.clear();
	res.a[1][1] = 1;
	res.a[2][2] = 1;
	while (n){
		if (n & 1){
			res = res * t;
		}
		n >>= 1;
		t = t * t;
	}
	return res;
}
ll n, x, y, a, b;
int main()
{
	while(~scanf("%lld %lld %lld %lld %lld", &n, &x, &y, &a, &b)){
		ll fib1, fib2;
		p temp;
		temp.clear();
		temp.a[1][2] = temp.a[2][1] = temp.a[2][2] = 1;
		if (n == 1){
			printf("%lld\n", x % mod);
		}
		else if (n == 2){
			printf("%lld\n", y % mod);
		}
		else {
			p ans = qpow(temp, n - 2);
			fib1 = ans.a[2][1];
			fib2 = ans.a[2][2];
			ll z = fib1 + fib2 - 1;
			ll res = qpow(x, fib1 % (mod - 1), mod);
			res = qc(res, qpow(y, fib2 % (mod - 1), mod), mod);
			a = qpow(a, b, mod);
			res = qc(res, qpow(a, z, mod), mod); 
			res %= mod;
			if (x % mod == 0 || y % mod == 0 || a % mod == 0){
				res = 0;
			}
			printf("%lld\n", res);
		}
	}
	return 0;
}
posted @ 2020-04-11 14:03  correct  阅读(128)  评论(0)    收藏  举报