2020牛客寒假算法基础集训营1
J u’s的影响力
题意
如题。
思路
我们可以发现,x和y的幂次是斐波那契数列的某一项,ab的幂次的递推公式为F[i] = F[i-1] + F[i-2] +1。所以我们可以用矩阵快速幂跑出幂次。但是由于幂次过大,无法直接求解,所以我们需要再套一个欧拉降幂,也就是幂次的递推时的模数为MOD-1。
坑点
要注意幂次模完之后可能会是0。
啊啊啊啊啊!卡了我一晚上!!!
当前时间:
Code
#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
using namespace std;
typedef long long ll;
typedef vector<int> VI;
typedef vector<VI> VII;
typedef vector<VII> VIII;
typedef pair<int, int> PII;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
const ll MOD = 1e9 + 7;
const ll MODD = 1e9 + 6;
ll qpow(ll a, ll b, ll p)
{
ll ret = 1;
a %= p;
while(b)
{
if(b&1) ret = ret*a%p;
a = a*a%p;
b >>= 1;
}
return ret;
}
struct Mat
{
int row,col;
ll a[5][5];
};
Mat mat_mul(Mat A,Mat B)
{
Mat C;
C.row=A.row;
C.col=B.col;
for(int i=1; i<=C.row; i++)
{
for(int j=1; j<=C.col; j++)
{
C.a[i][j]=0;
for(int k=1; k<=A.col; k++)
C.a[i][j]=(C.a[i][j]+A.a[i][k]*B.a[k][j]%MODD)%MODD;
}
}
return C;
}
///N为需要求第N项,A为初始矩阵(前几项),M为转移矩阵
Mat mat_quick_pow(ll N,Mat A,Mat M)
{
Mat ans=A,B=M;
while(N)
{
if(N&1) ans=mat_mul(B,ans);
B=mat_mul(B,B);
N >>= 1;
}
return ans;
}
int main()
{
ll n, x, y, a, b;
scanf("%lld%lld%lld%lld%lld", &n, &x, &y, &a, &b);
a %= MOD;
x %= MOD;
y %= MOD;
if(n == 1) printf("%lld\n", x);
else if(n == 2) printf("%lld\n", y);
else if(n == 3) printf("%lld\n", ((x*y)%MOD)*qpow(a, b, MOD)%MOD);
else
{
Mat A,M;
A.row=2;A.col=1;
A.a[1][1]=1;A.a[2][1]=0;
M.row=M.col=2;
M.a[1][1]=1;M.a[1][2]=1;
M.a[2][1]=1;M.a[2][2]=0;
Mat ANS = mat_quick_pow(n-2, A, M);
ll xx = ANS.a[2][1] + MODD;
ll yy = ANS.a[1][1] + MODD;
ll ans = qpow(x, xx, MOD)*qpow(y, yy, MOD)%MOD;
A.row=3;A.col=1;
A.a[1][1]=1;A.a[2][1]=0;A.a[3][1]=1;
M.row=M.col=3;
M.a[1][1]=1;M.a[1][2]=1;M.a[1][3]=1;
M.a[2][1]=1;M.a[2][2]=0;M.a[2][3]=0;
M.a[3][1]=0;M.a[3][2]=0;M.a[3][3]=1;
ll bb = mat_quick_pow(n-3, A, M).a[1][1];
ans = ans*qpow(qpow(a, b, MOD), bb, MOD)%MOD;
printf("%lld\n", ans);
}
return 0;
}