1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
| #include<cmath> #include<cstdio> #include<cstring> #define fo(i,a,b) for(int i=a;i<=b;i++) using namespace std;
typedef long long LL;
const int maxsqrtp=5e4+5;
struct Arr{ LL n[2][2]; };
LL n,p; int k;
LL mi(LL x,LL y) { LL re=1; for(; y; y>>=1, (x*=x)%=p) if (y&1) (re*=x)%=p; return re; }
int g,p0,pr[maxsqrtp]; void find_g() { int sqrtp=sqrt(p), pp=p-1; p0=0; fo(i,2,sqrtp) if (pp%i==0) { pr[++p0]=i; while (pp%i==0) pp/=i; } if (pp>1) pr[++p0]=pp; for(g=2; ; g++) { bool pd=1; fo(i,1,p0) if (mi(g,(p-1)/pr[i])==1) {pd=0; break;} if (pd) return; } }
Arr F,I; Arr mul(Arr a,Arr b) { Arr re; re.n[0][0]=(a.n[0][0]*b.n[0][0]+a.n[0][1]*b.n[1][0])%p; re.n[0][1]=(a.n[0][0]*b.n[0][1]+a.n[0][1]*b.n[1][1])%p; re.n[1][0]=(a.n[1][0]*b.n[0][0]+a.n[1][1]*b.n[1][0])%p; re.n[1][1]=(a.n[1][0]*b.n[0][1]+a.n[1][1]*b.n[1][1])%p; return re; } Arr mulnum(Arr a,LL b) { (a.n[0][0]*=b)%=p; (a.n[0][1]*=b)%=p; (a.n[1][0]*=b)%=p; (a.n[1][1]*=b)%=p; return a; } Arr plusI(Arr a) { (a.n[0][0]+=1)%=p; (a.n[1][1]+=1)%=p; return a; } Arr Mi(Arr x,LL y) { Arr re=I; for(; y; y>>=1, x=mul(x,x)) if (y&1) re=mul(re,x); return re; }
int T; int main() { F.n[0][0]=F.n[0][1]=F.n[1][0]=1; F.n[1][1]=0; I.n[0][0]=I.n[1][1]=1; scanf("%d",&T); while (T--) { scanf("%lld %d %lld",&n,&k,&p); find_g(); LL w0=mi(g,(p-1)/k); LL ans=0, w=1; fo(j,0,k-1) { Arr t=Mi(plusI(mulnum(F,w)),n); (ans+=t.n[0][0])%=p; (w*=w0)%=p; } printf("%lld\n",ans*mi(k,p-2)%p); } }
|