ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【HDOJ 5895】Mathematician QSC 矩阵快速幂+欧拉定理

2022-07-23 00:33:36  阅读:110  来源: 互联网

标签:QSC Matrix Mathematician ll long int 5895 ans mod


参考 https://blog.csdn.net/queuelovestack/article/details/52577212

题目链接

https://acm.hdu.edu.cn/showproblem.php?pid=5895

思路

用f(n-1)乘上f(n)=f(n-2)+2*f(n-1),再通过移项、累加后得 g[n]=f[n] * f[n+1]/2

那么就可以首先通过矩阵快速幂计算出g(n*y)的值

关于除以2的处理:
因为2不一定和p互质,不一定能用费马小定理求出2的逆元

要求 $ \frac{a}{b} \ mod \ p $,不妨先设其值为d,
=> \(\frac{a}{b}=k*p+d\)
=> \(a=k*b*p+b*d\)
=> \(\frac{a \ mod (b*p)}{b}=d\)
⭐因此模数变成了 b*p !!!⭐

因为 \(x^{g(n*y)}\) 肯定大于 $\phi(s+1) $,所以这个地方可以用欧拉定理来降幂

最后再用快速幂求出最终答案

code

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2;
int t;
ll y,n,x,s;
struct Matrix{
	long long m[2][2];
};

Matrix mul(Matrix a,Matrix b,ll mod){
	Matrix c;
	for(int i=0;i<N;i++){  //NxN的矩阵 
		for(int j=0;j<N;j++){
			c.m[i][j]=0;
		}
	}
	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]+=a.m[i][k]*b.m[k][j];
				c.m[i][j]%=mod;
			}
		}
	}
	return c;
}

Matrix ksm(Matrix a,ll t,ll mod){   //t可能要开longlong 
	Matrix ans;
	for(int i=0;i<N;i++){  //NxN的矩阵 
		for(int j=0;j<N;j++){
			if(i==j) ans.m[i][j]=1; 
			else ans.m[i][j]=0;
		}
	}
	while(t){
		if(t&1){
			ans=mul(ans,a,mod);
		}
		a=mul(a,a,mod);
		t/=2;
	}
	return ans;
}

ll qpow(ll a,ll b,ll mod){
	ll ans=1;
    a%=mod;
	while(b){
		if(b%2){
			ans*=a;
			ans%=mod; 
		}
		a*=a;
		a%=mod;  //注意这里也需要取模 
		b/=2;
	}
	return ans;
}

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

ll f(ll id,ll mod){
    Matrix init;
    for(int i=0;i<2;i++){
        for(int j=0;j<2;j++){
            if(i==0&&j==0) init.m[i][j]=1;
            else init.m[i][j]=0;
        }
    }
    Matrix a;
    a.m[0][0]=2; a.m[0][1]=1;
    a.m[1][0]=1; a.m[1][1]=0;
    Matrix ans=mul(init,ksm(a,id-1,mod),mod);
    return ans.m[0][0]*ans.m[0][1];
}

int main(){
    cin>>t;
    while(t--){
        scanf("%lld%lld%lld%lld",&n,&y,&x,&s);
        s+=1;
        ll X=1ll*n*y;
        ll p=2*Euler(s);
        X=f(X+1,p)%p/2+p/2;
        printf("%lld\n",qpow(x,X,s));
    }
    system("pause");
    return 0;
}

标签:QSC,Matrix,Mathematician,ll,long,int,5895,ans,mod
来源: https://www.cnblogs.com/re0acm/p/16508333.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有