题解:P11888 「Stoi2025」爱的飞行日记
littlez_meow · · 题解
都是很典的技巧,比较简单。
首先我们先不加证明的给出几个很经典的引理:
下面开始推式子。写出原式:
使用引理
使用引理
枚举
具体地,
整理得:
枚举
整理:
指数上的括号里可以补上
枚举
预处理括号里面的前缀积就可以用整除分块单次
至于预处理
总的时间复杂度是
#include<bits/stdc++.h>
#define F(i,a,b) for(int i(a),i##i##end(b);i<=i##i##end;++i)
#define R(i,a,b) for(int i(a),i##i##end(b);i>=i##i##end;--i)
#define ll long long
#define File(a) freopen(#a".in","r",stdin);freopen(#a".out","w",stdout)
using namespace std;
const int MAXN=2e7+1,MOD=37426667,EXPO=37426666;
inline ll qpow(ll base,ll expo){
ll res=1;
while(expo){
(expo&1)&&(res=res*base%MOD);
base=base*base%MOD,expo>>=1;
}
return res;
}
inline ll qpowe(ll base,ll expo){
ll res=1;
while(expo){
(expo&1)&&(res=res*base%EXPO);
base=base*base%EXPO,expo>>=1;
}
return res;
}
int pr[MAXN],cnt;
bool vis[MAXN];
short mu[MAXN];
inline void init(){
mu[1]=1;
F(i,2,MAXN-1){
!vis[i]&&(pr[++cnt]=i,mu[i]=-1);
F(j,1,cnt){
int t=i*pr[j];
if(t>=MAXN) break;
vis[t]=1;
if(i%pr[j]==0) break;
else mu[t]=-mu[i];
}
}
return;
}
int inv[MOD],fib[MAXN],mul[MAXN];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
init();
inv[1]=1;
F(i,2,MOD-1) inv[i]=MOD-MOD/i*1ll*inv[MOD%i]%MOD;
fib[1]=fib[2]=mul[0]=mul[1]=mul[2]=1;
F(i,3,MAXN-1) (fib[i]=fib[i-1]+fib[i-2])>=MOD&&(fib[i]-=MOD),mul[i]=fib[i];
F(i,1,cnt) for(int t=(MAXN-1)/pr[i],j=t*pr[i];j>=pr[i];j-=pr[i],--t) mul[j]=mul[j]*1ll*inv[mul[t]]%MOD;
F(i,1,MAXN-1) mul[i]=mul[i-1]*1ll*mul[i]%MOD;
int T,m;
for(cin>>T;T;--T){
ll n,ans=1;
cin>>n>>m;
ll qwq=qpowe(m,n);
for(int l=1,r;l<=m;l=r+1){
int t=m/l;
r=m/t;
ans=ans*qpow(mul[r]*1ll*inv[mul[l-1]]%MOD,qwq-qpowe(m-t,n)+EXPO)%MOD;
}
cout<<ans<<"\n";
}
return 0;
}