題目大意
給定
對
其中
一個測試點
其中
保證
題目分析
好一道腦洞題。
題目相當於求
把斐波那契數列寫成矩陣形式,令
則
先不考慮這個
因爲單位矩陣
現在考慮怎麼解決
怎麼構造呢?考慮使用單位根的性質來構造。
令
這個怎麼證明?你等比數列求和一下,把
於是答案等於
考慮把
枚舉
原根暴力找(一般比較小),判斷的話只用檢查
時間複雜度
代碼實現
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long LL;
const int L=31622;
int pri[L+5],p[L+5],a[L+5];
bool mark[L+5];
int T,K,P,g,cnt;
LL n;
struct matrix
{
int num[2][2];
int r,c;
inline matrix operator*(matrix const mat)const
{
matrix ret;ret.r=r,ret.c=mat.c,memset(ret.num,0,sizeof ret.num);
for (int i=0;i<ret.r;++i)
for (int k=0;k<c;++k)
if (num[i][k])
for (int j=0;j<ret.c;++j)
(ret.num[i][j]+=1ll*num[i][k]*mat.num[k][j]%P)%=P;
return ret;
}
inline matrix operator+(matrix const mat)const
{
matrix ret;ret.r=r,ret.c=c;
for (int i=0;i<ret.r;++i)
for (int j=0;j<ret.c;++j)
ret.num[i][j]=(num[i][j]+mat.num[i][j])%P;
return ret;
}
inline matrix operator*(int const k)const
{
matrix ret;ret.r=r,ret.c=c;
for (int i=0;i<ret.r;++i)
for (int j=0;j<ret.c;++j)
ret.num[i][j]=1ll*num[i][j]*k%P;
return ret;
}
}A,I,res;
inline matrix operator*=(matrix &x,matrix y){return x=x*y;}
inline matrix operator+=(matrix &x,matrix y){return x=x+y;}
inline matrix operator*=(matrix &x,int y){return x=x*y;}
inline matrix operator^(matrix x,LL y)
{
matrix ret=I;
for (;y;y>>=1,x*=x) if (y&1) ret*=x;
return ret;
}
int quick_power(int x,int y)
{
int ret=1;
for (;y;y>>=1,x=1ll*x*x%P) if (y&1) ret=1ll*ret*x%P;
return ret;
}
void pre()
{
mark[1]=1;
for (int i=2;i<=L;++i)
{
if (!mark[i]) pri[++pri[0]]=i;
for (int j=1;j<=pri[0];++j)
{
if (1ll*i*pri[j]>L) break;
mark[i*pri[j]]=1;
if (!(i%pri[j])) break;
}
}
A.r=A.c=2,A.num[0][0]=A.num[0][1]=A.num[1][0]=1;
I.r=I.c=2,I.num[0][0]=I.num[1][1]=1;
}
void calc()
{
cnt=0;
int x=P-1;
for (int i=1;i<=pri[0]&&1ll*pri[i]*pri[i]<=P-1&&x>1;++i)
if (!(x%pri[i]))
{
p[++cnt]=pri[i],a[cnt]=0;
for (;!(x%pri[i]);x/=pri[i]) ++a[cnt];
}
if (x>1) p[++cnt]=x,a[cnt]=1;
g=0;
for (int i=2;i<P&&!g;++i)
{
bool judge=1;
for (int j=1;j<=cnt&&judge;++j) judge&=quick_power(i,(P-1)/p[j])!=1;
if (judge) g=i;
}
int w=quick_power(g,(P-1)/K);
res.r=res.c=2,memset(res.num,0,sizeof res.num);
for (int j=0;j<K;++j) res+=((A*quick_power(w,j)+I)^n);
res*=quick_power(K,P-2);
}
int main()
{
freopen("you.in","r",stdin),freopen("you.out","w",stdout);
for (pre(),scanf("%d",&T);T--;) scanf("%lld%d%d",&n,&K,&P),calc(),printf("%d\n",res.num[0][0]);
fclose(stdin),fclose(stdout);
return 0;
}