2020牛客寒假算法基础集训营1
题意:
思路:
写几项,推导x,y,a^b的系数即可,然后找好和项数对应的关系
x,y都是斐波那契的某一项,然后正常看的话,a^b的系数应该是前两项之和加1,仔细观察发现,它的系数也是斐波那契的某一项减1即可
用矩阵快速幂算系数,因为数据大,然后还有就是用欧拉降幂欧拉降幂传送门
1e9+7是素数,它的欧拉函数值是1e9+6
我的推导过程
代码:
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <math.h>
#include <map>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
const int maxn=3e5+50;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const int phi=1e9+6;
ll quick(ll a,ll b){//快速幂
ll ans=1;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b/=2;
}
return ans%mod;
}
struct sa
{
ll m[2][2];
};
sa Mul(sa a,sa b)//矩阵乘法
{
sa c;
memset(c.m,0, sizeof(c.m));
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j]%phi)%phi;
return c;
}
sa quickjz(sa a,ll n)//矩阵快速幂
{
sa res;
memset(res.m,0, sizeof(res.m));
res.m[0][0]=1;
res.m[1][1]=1;
while(n)
{
if(n&1)
res=Mul(res,a);
n/=2;
a=Mul(a,a);
}
return res;
}
int main()
{
ll n,x,y,a,b;
scanf("%lld%lld%lld%lld%lld",&n,&x,&y,&a,&b);
if(n==1){
printf("%lld\n",x%mod);
return 0;
}
if(n==2){
printf("%lld\n",y%mod);
return 0;
}
x%=mod;
y%=mod;
a%=mod;
if(a==0||x==0||y==0){//需要特判
printf("0\n");
return 0;
}
sa k={1,1,1,0},q={1,1,1,0},l={1,1,1,0};
k=quickjz(k,n-3);
ll p1=(k.m[1][0]+k.m[1][1])%phi;//x的系数
q=quickjz(q,n-2);
ll p2=(q.m[1][0]+q.m[1][1])%phi;//y的系数
l = quickjz(l, n - 1);
ll p3=(l.m[1][0]+l.m[1][1]-1);//a^b的系数
a=quick(a,b);
ll ans=1;
ans=quick(x,p1)*quick(y,p2)%mod*quick(a,p3)%mod;
printf("%lld\n",ans);
return 0;
}