u's的影响力 (欧拉降幂,矩阵快速幂)

题目链接

欧拉降幂:

欧拉降幂参考博客

存欧拉函数模板:


ll phi(ll n) {
	ll ans = 1;
	for (ll i = 2; i*i <= n; i++) {
		if (n%i == 0) {
			n /= i;
			ans *= i - 1;
			while (n%i == 0) {
				n /= i;
				ans *= i;
			}
		}
	}
	if (n > 1) ans *= n - 1;
	return ans;
}

然后解法:

 f(1)=x                                    f(1)=x^1 * y^0 * a^(1+0-1)b

f(2)= y                                    f(2)= x^0 * y^1 * a^(0+1-1)b

f(3)=x * y * a^b                      f(3)=x * y * a^(1+1-1)b

 f(4) = x * y^2 * a^2b             f(4) = x * y^2 * a^(1+2-1)b

f(5) = x^2 * y^3 * a^4b          f(5) = x^2 * y^3 * a^(2+3-1)b

f(6) = x^3 * y^5 * a^7b          f(6) = x^3 * y^5 * a^(3+5-1)b

易得:f( n )  = x^fab(n-2)  * y^fab(n-1)  * a^(fab(n)-1)*b

鉴于a^(fab(n)-1)*b 指数过大,需要使用 欧拉降幂

鉴于fab(n) n比较大,需要使用 矩阵快速幂 求斐波拉契数

其次,当a%mod==0 时,即gcd(a,mod)!=1,而a^(fab(n)-1)*b算出来会是1,但是a^(fab(n)-1)*b%mod=0 ,则需要特判

#include<bits/stdc++.h>
#define ll long long 
ll mod=1e9+7; 
using namespace std;
ll n,x,y,a,b;
ll res[2][2];
void mul(ll a[][2],ll b[][2] )//矩阵乘法 
{
	ll t[2][2];
	memset(t,0,sizeof(t));
	for(int i=0;i<2;i++)
	{
		for(int j=0;j<2;j++)
		{
			for(int k=0;k<2;k++)
			t[i][j]+=a[i][k]%mod*b[k][j]%mod;
			t[i][j]%=mod;
		}
	}
	for(int i=0;i<2;i++)
	{
		for(int j=0;j<2;j++)
			a[i][j]=t[i][j];
	}
}
void Pow(ll a[][2],ll p)//矩阵快速幂 
{
	memset(res,0,sizeof(res));
	for(int i=0;i<2;i++) res[i][i]=1; //!!!矩阵初始化 	
	while(p)
	{
		if(p&1) mul(res,a);
		mul(a,a);
		p/=2;
	}	
}
ll fab(ll n) 
{
	if(n<=2) return 1;
	ll tmp[2][2];
	tmp[0][0]=1;
	tmp[0][1]=1;
	tmp[1][0]=1;
	tmp[1][1]=0;
	Pow(tmp,n-2);
	ll ans=(res[0][0]+res[0][1])%mod;
	return ans;	
}
ll ksm(ll a,ll b)//快速幂 
{
	ll ans=1;
	ll hh=a%mod;//!!!mod
	while(b)
	{
		if(b&1) ans*=hh;
		ans%=mod;
		hh*=hh;
		hh%=mod;
		b/=2;
	}
	return ans;
}
int main()
{
	cin>>n>>x>>y>>a>>b;
	
	mod--;//费马小定理gcd(a,mod)==1 指数对1e9+6 取模 
	ll X=fab(n-2);
	ll Y=fab(n-1);
	ll A=(X+Y-1+mod)%(mod);
	A%=mod;
	mod++;
	if(n<=2)
	{
		if(n==1)printf("%lld\n",x%mod);
		else printf("%lld\n",y%mod);
		return 0;
	}
	if(a%mod==0||x%mod==0||y%mod==0)//要注意a是1000000007的倍数的特殊情况 即gcd(a,mod)!=1,
									//不能用费马小定律指数对1e9+6 取模。
	{
		printf("0\n");
		return 0;
	}
	ll ans=ksm(x,X)%mod*ksm(y,Y)%mod*ksm(ksm(a,b),A)%mod;
	printf("%lld\n",ans);
	return 0;
}
发布了44 篇原创文章 · 获赞 6 · 访问量 1166

猜你喜欢

转载自blog.csdn.net/qq_43868883/article/details/104186752