(矩陣快速冪+費馬小定理)2020牛客寒假算法基礎集訓營1J.u’s的影響力

2020牛客寒假算法基礎集訓營1J.u’s的影響力

思路:

臨時補了矩陣快速冪,沒想到敗在了費馬小定理上。
由原式得:
f(1)=x
f(2)=y
f(3)=f(1)*f(2)*ab
f(4)=f(2)*f(3)*ab=f(1)*f2(2)*(ab)2
f(5)=f(3)*f(4)*ab=f2(1)*f3(2)*(ab)4
f(6)=f(4)*f(5)*ab=f3(1)*f5(2)*(ab)7
……
發現對於n>2的情況,f(n)=fFib(n-2)(1)*fFib(n-1)(2)*(ab)Fib(n-2)+Fib(n-1)-1,Fib(i)爲斐波那契數列的第i項,利用矩陣快速冪就可以求出。
由於斐波那契數列增長的很快,所以ap,p會是很大的數。這裏要用到費馬小定理。
如果p是一個質數,而a不是p的倍數,ap−1≡1(mod p)
所以我們只要對冪取1e9+6的模就行了。
對於n=1,n=2,x,y,a是1e9+7倍數要特判。

代碼:

#include<bits/stdc++.h>
#define pii pair<int,int>
#define ll long long
#define cl(x,y) memset(x,y,sizeof(x))
#define ct cerr<<"Time elapsed:"<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
const int N=1e6+10;
const int mod=1e9+7;
const int maxn=0x3f3f3f3f;
const int minn=0xc0c0c0c0;
const int inf=99999999;
using namespace std;
struct mat
{
	ll m[5][5];
	mat()
	{
		cl(m,0);
	}
};
mat mul(mat x1,mat y1,ll p)
{
	mat z1;
	int i,j,k;
	for(i=1;i<=2;i++)
		for(j=1;j<=2;j++)
			for(k=1;k<=2;k++)
				z1.m[i][j]=(z1.m[i][j]+x1.m[i][k]*y1.m[k][j])%p;
	return z1;
}
mat matpow(mat x1,ll n,ll p)
{
	mat y1;
	int i,j;
	for(i=1;i<=2;i++)
		for(j=1;j<=2;j++)
			y1.m[i][j]=i==j?1:0;
	while(n)
	{
		if(n&1)
			y1=mul(y1,x1,p);
		x1=mul(x1,x1,p);
		n>>=1;
	}
	return y1;
}
ll quickpow(ll a,ll b)
{
	ll res=1;
	while(b)
	{
		if(b&1)
			res=(res*a)%mod;
		a=(a*a)%mod;
		b>>=1;
	}
	return res;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	ll n,x,y,a,b;
	cin>>n>>x>>y>>a>>b;	
	if(x%mod==0 || y%mod==0 || a%mod==0)
		cout<<0<<endl;
	else if(n==1)
		cout<<x%mod<<endl;
	else if(n==2)
		cout<<y%mod<<endl;
	else
	{
		x%=mod;
		y%=mod;
		ll f=quickpow(a%mod,b);
		mat x1;
		x1.m[1][1]=x1.m[1][2]=x1.m[2][1]=1;
		x1=matpow(x1,n-2,mod-1);
		ll ans=(quickpow(x,x1.m[2][1])%mod*quickpow(y,x1.m[1][1])%mod*quickpow(f,(x1.m[1][1]+x1.m[2][1]-1)))%mod;
		cout<<ans<<endl;
	}
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章