给定函数F(0,m)=m+1,F(n,0)=F(n-1,1),F(n,m)=F(n-1,F(n,m-1))。
多次询问求F(n,m)%p,n,m1e18,p1e9。
题解:首先打表发现F(0,m)=m+1,F(1,m)=n+2,F(2,m)=2m+3,F(3,m)=2^m-3,然后考虑F(>=4,m),不难发现这玩意是2的2的2的2的…的2次方,当n=4时好像是m+3个2。考虑n=4这个怎么做,直接上扩展欧拉定理,打表发现F(4,>=3)就已经比1e9大了,所以不需要考虑2和p的关系以及b和phi(p)的关系之类的。
最后最坑的是,当n>=5时,把n=5,m=0判掉,剩下的都是非常非常多的2做幂次,也就是此时m不重要,因此在m变小之前p就变成0了,直接随便输出个什么东西就可以了。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<unordered_map>
#include<assert.h>
#define lint long long
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
unordered_map<int,int> PHI;
inline lint F(int m,lint n)
{
if(m==0) return n+1;
if(m==1) return n+2;
if(m==2) return 2*n+3;
if(n==0) return F(m-1,1);
return F(m-1,F(m,n-1));
}
inline int fast_pow(int x,lint k,int p,int ans=1)
{ for(ans%=p,x%=p;k;k>>=1,x=(lint)x*x%p) (k&1)?ans=(lint)ans*x%p:0;return ans; }
inline int Phi(int p)
{
if(p==1) return 1;
if(PHI.count(p)) return PHI[p];
for(int i=2,x;i<=p/i;i++) if(p%i==0)
{
if((x=p/i)%i) return PHI[p]=Phi(x)*(i-1);
else return PHI[p]=Phi(x)*i;
}
return PHI[p]=p-1;
}
inline int solve(lint n,int p)
{
if(n==0) return 16%p;
if(n==1) return 65536%p;
if(p==1) return 0;int t=Phi(p);
return fast_pow(2,solve(n-1,t)+t,p)%p;
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
lint m,n;int p;scanf("%lld%lld%d",&m,&n,&p);
if(m==0) printf("%lld\n",(n+1)%p);
else if(m==1) printf("%lld\n",(n+2)%p);
else if(m==2) printf("%lld\n",(2*n+3)%p);
else if(m==3) printf("%d\n",(fast_pow(2,n+3,p)-3%p+p)%p);
else if(m==4) printf("%d\n",(solve(n,p)-3%p+p)%p);
else if(m==5&&n==0) printf("%d\n",65533%p);
else printf("%d\n",(solve(123321,p)-3%p+p)%p);
}
return 0;
}