传送门
f
[
0
]
=
0
,
f
[
1
]
=
1
,
f
[
i
]
=
f
[
i
−
1
]
+
f
[
i
−
2
]
(
i
⩾
2
)
f[0]=0,f[1]=1,f[i]=f[i-1]+f[i-2](i \geqslant2)
f[0]=0,f[1]=1,f[i]=f[i−1]+f[i−2](i⩾2)
a
n
s
=
∏
i
=
1
n
∏
j
=
1
m
f
[
g
c
d
(
i
,
j
)
]
ans=\prod_{i=1}^{n} \prod_{j=1}^{m} {f[gcd(i,j)]}
ans=i=1∏nj=1∏mf[gcd(i,j)]
a
n
s
=
∏
i
=
1
n
∏
j
=
1
m
∏
t
=
1
m
i
n
(
n
,
m
)
[
g
c
d
(
i
,
j
)
=
=
t
]
f
[
t
]
ans=\prod_{i=1}^{n} \prod_{j=1}^{m} \prod_{t=1}^{min(n,m)} {[gcd(i,j)==t]f[t]}
ans=i=1∏nj=1∏mt=1∏min(n,m)[gcd(i,j)==t]f[t]
a
n
s
=
∏
t
=
1
m
i
n
(
n
,
m
)
f
[
t
]
∑
i
=
1
n
∑
j
=
1
m
[
g
c
d
(
i
,
j
)
=
=
t
]
ans=\prod_{t=1}^{min(n,m)} f[t]^{\sum_{i=1}^{n} \sum_{j=1}^{m} {[gcd(i,j)==t]}}
ans=t=1∏min(n,m)f[t]∑i=1n∑j=1m[gcd(i,j)==t]
令指数为
p
[
t
]
p[t]
p[t]:
p
[
t
]
=
∑
i
=
1
n
∑
j
=
1
m
[
g
c
d
(
i
,
j
)
=
=
t
]
p[t]={\sum_{i=1}^{n} \sum_{j=1}^{m} {[gcd(i,j)==t]}}
p[t]=i=1∑nj=1∑m[gcd(i,j)==t]
=
∑
i
=
1
⌊
n
t
⌋
∑
j
=
1
⌊
m
t
⌋
[
g
c
d
(
i
,
j
)
=
=
1
]
={\sum_{i=1}^{\lfloor \frac{n}{t}\rfloor} \sum_{j=1}^{\lfloor \frac{m}{t}\rfloor} {[gcd(i,j)==1]}}
=i=1∑⌊tn⌋j=1∑⌊tm⌋[gcd(i,j)==1]
=
∑
i
=
1
⌊
n
t
⌋
∑
j
=
1
⌊
m
t
⌋
∑
d
∣
i
,
d
∣
j
μ
(
d
)
={\sum_{i=1}^{\lfloor \frac{n}{t}\rfloor} \sum_{j=1}^{\lfloor \frac{m}{t}\rfloor} \sum_{d|i,d|j}{\mu(d)}}
=i=1∑⌊tn⌋j=1∑⌊tm⌋d∣i,d∣j∑μ(d)
=
∑
d
=
1
μ
(
d
)
∗
⌊
n
d
∗
t
⌋
⌊
m
d
∗
t
⌋
=\sum_{d=1}{\mu(d)*\lfloor \frac{n}{d*t}\rfloor \lfloor \frac{m}{d*t}\rfloor}
=d=1∑μ(d)∗⌊d∗tn⌋⌊d∗tm⌋
这时候,一次询问需要:
O
(
n
)
O(n)
O(n)枚举
t
t
t,每次再
O
(
n
t
)
O(\sqrt{\frac{n}{t}})
O(tn)求和。
一个优化套路:令
T
=
d
∗
t
T=d*t
T=d∗t,于是:
p
[
t
]
=
∑
t
∣
T
,
T
∈
[
1
,
n
]
μ
(
T
t
)
∗
⌊
n
T
⌋
⌊
m
T
⌋
p[t]=\sum_{t|T,T\in[1,n]}{\mu(\frac{T}{t})*\lfloor \frac{n}{T}\rfloor \lfloor \frac{m}{T}\rfloor}
p[t]=t∣T,T∈[1,n]∑μ(tT)∗⌊Tn⌋⌊Tm⌋
代入答案:
a
n
s
=
∏
t
=
1
m
i
n
(
n
,
m
)
f
[
t
]
∑
t
∣
T
,
T
∈
[
1
,
n
]
μ
(
T
t
)
∗
⌊
n
T
⌋
⌊
m
T
⌋
ans=\prod_{t=1}^{min(n,m)} f[t]^{\sum_{t|T,T\in[1,n]}{\mu(\frac{T}{t})*\lfloor \frac{n}{T}\rfloor \lfloor \frac{m}{T}\rfloor}}
ans=t=1∏min(n,m)f[t]∑t∣T,T∈[1,n]μ(tT)∗⌊Tn⌋⌊Tm⌋
交换
T
T
T和
t
t
t的枚举顺序:
a
n
s
=
∏
T
=
1
m
i
n
(
n
,
m
)
∏
t
∣
T
f
[
t
]
μ
(
T
t
)
∗
⌊
n
T
⌋
⌊
m
T
⌋
ans=\prod_{T=1}^{min(n,m)} \prod_{t|T} f[t]^{\mu(\frac{T}{t})*\lfloor \frac{n}{T}\rfloor \lfloor \frac{m}{T}\rfloor}
ans=T=1∏min(n,m)t∣T∏f[t]μ(tT)∗⌊Tn⌋⌊Tm⌋
a
n
s
=
∏
T
=
1
m
i
n
(
n
,
m
)
(
∏
t
∣
T
f
[
t
]
μ
(
T
t
)
)
⌊
n
T
⌋
⌊
m
T
⌋
ans=\prod_{T=1}^{min(n,m)} (\prod_{t|T} f[t]^{\mu(\frac{T}{t})})^{\lfloor \frac{n}{T}\rfloor \lfloor \frac{m}{T}\rfloor}
ans=T=1∏min(n,m)(t∣T∏f[t]μ(tT))⌊Tn⌋⌊Tm⌋
令
R
[
T
]
=
∏
t
∣
T
f
[
t
]
μ
(
T
t
)
R[T]=\prod_{t|T} f[t]^{\mu(\frac{T}{t})}
R[T]=∏t∣Tf[t]μ(tT),这个东西可以调和级数预处理。
处理完过后,一次询问就变为了
O
(
n
)
O(\sqrt{n})
O(n)。于是就做完了。
注意一下可以优化的细节。
#include<bits/stdc++.h>
#define re register
#define cs const
cs int N=1e6+10,mod=1e9+7;
int T,n,m,iR[N],R[N],iF[N],F[N];
inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
inline int quickpow(int a,int b,int ret=1){
if(b<0) b+=mod-1;
for(;b;b>>=1,a=mul(a,a))
if(b&1)ret=mul(ret,a);
return ret;
}
inline int inv(int x){return quickpow(x,mod-2);}
int mark[N],P[N],mu[N],cnt=0;
inline void linear_sieves(){
mark[0]=mark[1]=1,mu[1]=1;
for(int re i=2;i<N;++i){
if(!mark[i]) P[++cnt]=i,mu[i]=-1;
for(int re j=1;j<=cnt&&i*P[j]<N;++j){
mark[i*P[j]]=1;
if(i%P[j]) mu[i*P[j]]=-mu[i];
else{mu[i*P[j]]=0;break;}
}
}
}
inline void prework(){
F[0]=0,iF[1]=F[1]=1,iR[0]=iR[1]=R[0]=R[1]=1;
for(int re i=2;i<N;++i) R[i]=1,iF[i]=quickpow(F[i]=add(F[i-1],F[i-2]),mod-2);
for(int re d=3;d<N;++d)
for(int re T=d,t=1;T<N;T+=d,++t)
if(mu[t]!=0) R[T]=mul(R[T],mu[t]==1?F[d]:iF[d]);
for(int re i=2;i<N;++i) R[i]=mul(R[i-1],R[i]),iR[i]=inv(R[i]);
}
inline int query(int n,int m,int ret=1){
for(int re i=1,j;i<=std::min(n,m);i=j+1){
j=std::min(n/(n/i),m/(m/i));
ret=mul(ret,quickpow(mul(R[j],iR[i-1]),1ll*(n/i)*(m/i)%(mod-1)));
}return ret;
}
int main(){
linear_sieves(),prework(),scanf("%d",&T);
while(T--) scanf("%d%d",&n,&m),printf("%d\n",query(n,m));
}