E. Product Oriented Recurrence(乘法递推转化成幂的加法)

const int N = 1e4+5;
void mul(ll c[][3], ll a[][3], ll b[][3])
{
	ll tmp[3][3] = {0};
	f(i, 0, 2)
		f(j, 0, 2)
		f(k, 0, 2)tmp[i][j] = (tmp[i][j] + a[i][k] * b[k][j]) % (mod-1);
	memcpy(c, tmp, sizeof tmp);
}
void jzksm(ll a[][3],ll n)
{
	ll tmp[3][3] = { 0 };
	f(i, 0, 2)tmp[i][i] = 1;
	while (n)
	{
		if (n & 1)mul(tmp, tmp, a);
		mul(a, a, a);
		n >>= 1;
	}
	memcpy(a, tmp, sizeof tmp);
}
void mul2(ll c[][5], ll a[][5], ll b[][5])
{
	ll tmp[5][5] = { 0 };
	f(i, 0, 4)
		f(j, 0, 4)
		f(k, 0, 4)tmp[i][j] = (tmp[i][j] + a[i][k] * b[k][j]) % (mod - 1);
	memcpy(c, tmp, sizeof tmp);
}
void jzksm2(ll a[][5], ll n)
{
	ll tmp[5][5] = { 0 };
	f(i, 0, 5)tmp[i][i] = 1;
	while (n)
	{
		if (n & 1)mul2(tmp, tmp, a);
		mul2(a, a, a);
		n >>= 1;
	}
	memcpy(a, tmp, sizeof tmp);
}
int main()//递推式中出现乘法考虑转化成幂的加法再用矩阵加速求解
{
	//freopen("in.txt", "r", stdin);	
	ll n, f1, f2, f3,k;
	cin >> n >> f1 >> f2 >> f3 >> k;
	ll a[3][3] = {0,0,1};
	ll b[3][3] = { 0,1,0 };
	ll c[3][3] = { 1,0,0 };
	ll f[3][3] = { 1,1,0,
					1,0,1,
					1,0,0 };
	jzksm(f, n-3);
	mul(a, a, f);
	ll ff[3][3]= { 1,1,0,
				1,0,1,
				1,0,0 };
	jzksm(ff, n - 3);
	mul(b, b, ff);
	ll fff[3][3] = { 1,1,0,
				1,0,1,
				1,0,0 };
	jzksm(fff, n - 3);
	mul(c, c, fff);
	ll ffff[5][5] = { 0,0,1,0,0,
					  1,0,1,0,0,
					  0,1,1,0,0,
					  0,0,1,1,0,
					  0,0,0,1,1 };
	ll base[5][5] = { 0,0,0,2,2 };
	jzksm2(ffff, n - 3);
	mul2(base, base, ffff);
	ll ans = quickmod(k, base[0][2], mod);
	ans = ans * quickmod(f1, a[0][0], mod) % mod;
	ans = ans * quickmod(f2, b[0][0], mod) % mod;
	ans = ans * quickmod(f3, c[0][0], mod) % mod;
	cout << ans << endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值