喵喵的遗憾
Time Limit: 20000/10000MS (Java/Others)
Memory Limit: 512000/256000KB (Java/Others)
Problem Description
喵喵因为太弱,没有进Final,终身遗憾。她就挂在了这个题目上。
已知:
F0 = 1 , F1 = 1 , F2 = 2 , Fn = Fn-1+Fn-2
求:
FFFn Mod P
( 也就是 F[ F[ F[n] ] ] % P )
Input
第一行一个整数 T 代表数据组数(T ≤ 20000)。 <del> 喵以人格担保时限肯定够!!!</del>
以下每行两个整数 N , P (0 ≤ N ≤ 109 , 1 ≤ P ≤ 109)
Output
对于每组数据输出一个整数代表答案。
Sample Input
4 1 2 2 3 4 35 4 31
Sample Output
1 2 34 3
Hint
F1 = 1 , F1 = 1 , F1 = 1
F2 = 2 , F2 = 2 , F2 = 2
F4 = 5 , F5 = 8 , F8 = 34
Source
Dshawn
Manager
题意:很直接。不用赘述了吧。
思路:这个是利用了斐波那契在模一个数下循环特性来做的有点类似,a^(b^(c^d....))%p这种题目。 我就不多说了。 请看网址:http://blog.csdn.net/acdreamers/article/details/10983813 里面讲得很清楚。 虽然没有证明。。。证明非我这种凡人能懂,所以没有也没关系啦。
代码:
#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <string.h>
#include <string>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
#define mp make_pair
#define rep(i,n) for(int i=0;i<n;++i)
#define clr(a,x) memset(a,x,sizeof(a))
#define LL long long
const int N=5000+5;
const LL inf=1e17;
int n,k;
LL C[2][2];
LL gcd(LL a,LL b)
{
while(a&&b) {
if(a>b)a%=b;
else b%=a;
}
return a+b;
}
LL lcm(LL a,LL b) { return a*b/gcd(a,b); }
void mul(LL A[2][2],LL B[2][2],LL mod,LL dst[2][2])
{
clr(C,0);
rep(i,2) rep(j,2) rep(k,2)
{
C[i][j]=(C[i][j]+(A[i][k]*B[k][j])%mod)%mod;
}
rep(i,2) rep(j,2) dst[i][j]=C[i][j];
}
void M_pow(LL base[2][2],LL p,LL mod,LL dst[2][2])
{
LL ret[2][2]; ret[0][0]=ret[1][1]=1; ret[0][1]=ret[1][0]=0;
while(p>0) {
if(p&1) mul(ret,base,mod,ret);
mul(base,base,mod,base);
p>>=1;
}
rep(i,2) rep(j,2) dst[i][j]=ret[i][j];
}
LL f1,f2;
void F(LL n,LL mod)
{
LL cell[2][2]; cell[0][0]=cell[0][1]=cell[1][0]=1;
cell[1][1]=0;
M_pow(cell,n-1,mod,cell);
f1=(cell[1][1]+cell[1][0])%mod; f2=(cell[0][1]+cell[0][0])%mod;
}
LL mul_pow(LL base,LL p,LL mod)
{
LL ret=1;
while(p>0) {
if(p&1) ret=(ret*base)%mod;
base=(base*base)%mod;
p>>=1;
}
return ret;
}
LL S[100000],c;
LL find_loop(LL mod)
{
if(mod==2) return 3;
else if(mod==3) return 8;
else if(mod==5) return 20;
LL p;
if(mul_pow(5,(mod-1)/2,mod)==1) p=mod-1;
else p=2*mod+2;
c=0;
for(LL i=1;i*i<=p;++i) {
if(p%i) continue;
LL x=i,y=p/i;
F(x,mod);
if(f1==0&&f2==1) return x;
if(y!=x) S[c++]=y;
}
for(int i=c-1;i>=0;--i) {
F(S[i],mod);
if(f1==0&&f2==1) return S[i];
}
return 0;
}
LL qpow(LL base,LL p)
{
LL ret=1;
while(p>0) {
if(p&1) ret*=base;
base*=base;
p>>=1;
}
return ret;
}
LL find_len(LL mod)
{
LL len=1;
for(LL i=2;i*i<=mod;++i) {
if(mod%i) continue;
LL cnt=0;
while(mod%i==0) {
++cnt;
mod/=i;
}
//LL k=pow(i,cnt-1)*find_loop(i);
len=lcm(len,qpow(i,cnt-1)*find_loop(i));
}
// cout<<find_loop(mod)<<endl;
if(mod>1) len=lcm(len,find_loop(mod));
return len;
}
//
//LL f[20000000];
//void check(LL mod)
//{
// mod=(rand()%3333)*1000+rand()%1000+2;
// // mod=9629625;
// //mod=25679;
// LL x=mod;
// printf("%d\n",mod);
// f[0]=1; f[1]=1;
// int a,b;
// for(int i=2;i<20000000;++i) {
// f[i]=(f[i-1]+f[i-2])%mod;
// if(f[i]==1&&f[i-1]==0) {
// a=i;
// printf("%d\n",i);
// break;
// }
// }
// b=find_len(mod);
// if(a!=b) {
// char a='a';
// }
//}
int main()
{
{
int x;
// while(1) check(1);
}
int T; cin>>T;
while(T--) {
LL n,mod; scanf("%lld%lld",&n,&mod);
if(n==0) {
printf("%lld\n",1%mod);
continue;
} else if(mod==1) {
printf("0\n");
continue;
}
LL len1=find_len(mod);
LL len2=find_len(len1);
LL ans;
F(n,len2); ans=f2;
F(ans,len1); ans=f2;
F(ans,mod); ans=f2;
printf("%lld\n",ans);
}
}