考虑把 T 提到最外面,与 n,m 无关的项提出来预处理, =T=1∏min{n,m}(t∣T∏f[t]μ(tT))⌊Tn⌋⌊Tm⌋
设 g[T]=t∣T∏f[t]μ(tT),因为 μ 的取值只有 −1,0,1,预处理 f 的逆元即可做到 O(nlogn) 预处理出 g。
每组数据对 T 整除分块,预处理 g 的前缀积及其逆元,并根据欧拉定理对指数模 (109+6) 减小常数,即可做到每组数据 O(nlog(109+5)) 的复杂度。
因此总的时间复杂度 O(nlog(109+7)+1000nlog(109+5))。
#include<algorithm>#include<iostream>#include<cstdlib>#include<cstring>#include<cstdio>#include<vector>#include<cctype>#include<cmath>#include<ctime>template<classT>inlinevoidread(T &res){char ch;bool flag =false; res =0;while(ch =getchar(),!isdigit(ch)&& ch !='-');
ch =='-'? flag =true: res = ch ^48;while(ch =getchar(),isdigit(ch))
res = res *10+ ch -48;
flag ? res =-res :0;}typedeflonglong ll;constint N =1e6+1;constint mod =1e9+7;int pri[N], f[N], inv_f[N], g[N], inv_g[N], miu[N];int T, n, m, pr, ans;bool vis[N];template<classT>inlinevoidput(T x){if(x >9)put(x /10);putchar(x %10+48);}inlinevoidadd(int&x,int y){
x += y;
x >= mod ? x -= mod :0;}inlineintksm(int x,int k){int res =1;while(k){if(k &1) res =1ll* res * x % mod;
x =1ll* x * x % mod; k >>=1;}return res;}template<classT>inline T Min(T x, T y){return x < y ? x : y;}intmain(){
f[0]=0; f[1]=1;for(int i =2; i < N;++i)
f[i]= f[i -1],add(f[i], f[i -2]);for(int i =1; i < N;++i)
inv_f[i]=ksm(f[i], mod -2);
miu[1]=1;for(int i =2; i < N;++i){if(!vis[i])
pri[++pr]= i, miu[i]=-1;for(int j =1; j <= pr &&1ll* pri[j]* i < N;++j){int tmp = pri[j]* i;
vis[tmp]=true;if(i % pri[j]==0){
miu[tmp]=0;break;}
miu[tmp]=-miu[i];}}for(int i =0; i < N;++i)
g[i]=1;for(int i =1; i < N;++i)for(int j = i, cnt =1; j < N; j += i,++cnt){int t = miu[cnt];if(!t)continue;
g[j]=1ll* g[j]*(t ==1? f[i]: inv_f[i])% mod;}for(int i =1; i < N;++i)
g[i]=1ll* g[i -1]* g[i]% mod;for(int i =0; i < N;++i)
inv_g[i]=ksm(g[i], mod -2);read(T);while(T--){read(n);read(m);if(n > m) std::swap(n, m);
ans =1;for(int i =1, x; i <= n; i = x +1){
x =Min(n /(n / i), m /(m / i));
ans =1ll* ans *ksm(1ll* g[x]* inv_g[i -1]% mod,1ll*(n / i)*(m / i)%(mod -1))% mod;}put(ans),putchar('\n');}}