E[i]=p^f[i]
f[i]表示斐波那契数列的第i项
E[i]%q
=p^f[i]%q
因为q<p,所以gcd(p,q)=1
所以p^phi(q)%q=1,注意q不一定是质数
先求f[i]%phi(q)的值,再用快速幂求值即可
f[i]表示斐波那契数列的第i项
E[i]%q
=p^f[i]%q
因为q<p,所以gcd(p,q)=1
所以p^phi(q)%q=1,注意q不一定是质数
先求f[i]%phi(q)的值,再用快速幂求值即可
按理说,用O(√n)的做法求phi,但是貌似卡不过去,那么直接枚举素数分解质因数就好了
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
#define maxn 100010
using namespace std;
int phi;
struct matrix
{
int a[3][3];
int x,y;
matrix operator*(matrix b)
{
matrix ans;
memset(ans.a,0,sizeof(ans.a));
ans.x=x;ans.y=b.y;
for (int i=1;i<=ans.x;i++)
for (int j=1;j<=ans.y;j++)
for (int k=1;k<=y;k++)
ans.a[i][j]=((long long)ans.a[i][j]+(long long)a[i][k]*b.a[k][j]%phi)%phi;
return ans;
}
}a,b;
int prime[maxn];
bool vis[maxn];
int tot,n,ans,p,T,q;
int power(int x,int y,int mod)
{
int ans=1;
while (y)
{
if (y&1) ans=(long long)ans*x%mod;
x=(long long)x*x%mod;
y>>=1;
}
return ans%mod;
}
int cal(int x)
{
int ans=x;
for (int i=1;i<=tot && (long long)prime[i]*prime[i]<=x;i++)
if (x%prime[i]==0)
{
while (x%prime[i]==0) x/=prime[i];
ans=ans/prime[i]*(prime[i]-1);
}
if (x!=1) ans=ans/x*(x-1);
return ans;
}
int calc(int x)
{
x--;
b.x=1;b.y=2;
b.a[1][1]=1;b.a[1][2]=0;
a.x=2;a.y=2;
a.a[1][1]=1;a.a[1][2]=1;
a.a[2][1]=1;a.a[2][2]=0;
while (x)
{
if (x&1) b=b*a;
a=a*a;
x>>=1;
}
return b.a[1][1];
}
int main()
{
scanf("%d%d",&T,&p);
n=100000;
for (int i=2;i<=n;i++)
{
if (!vis[i]) prime[++tot]=i;
for (int j=1;j<=tot && i*prime[j]<=n;j++)
{
vis[i*prime[j]]=1;
if (i%prime[j]==0) break;
}
}
while (T--)
{
scanf("%d%d",&n,&q);
phi=cal(q);
printf("%d\n",power(p,calc(n),q));
}
return 0;
}