求
∏
i
=
1
n
∏
i
=
1
m
f
[
(
i
,
j
)
]
\prod \limits_{i = 1}^{n} \prod \limits_{i = 1}^{m} f[(i, j)]
i=1∏ni=1∏mf[(i,j)]。
考虑枚举
t
=
(
i
,
j
)
t = (i, j)
t=(i,j),得:
∏
i
=
1
n
∏
i
=
1
m
f
[
(
i
,
j
)
]
\prod \limits_{i = 1}^{n} \prod \limits_{i = 1}^{m} f[(i, j)]
i=1∏ni=1∏mf[(i,j)]
=
∏
t
=
1
min
{
n
,
m
}
f
[
t
]
∑
i
=
1
n
∑
j
=
1
m
[
(
i
,
j
)
=
t
]
=\prod \limits_{t = 1}^{\min\{n, m\}} f[t] ^{\sum\limits_{i = 1}^{n} \sum\limits_{j = 1}^{m}[(i, j) =t]}
=t=1∏min{n,m}f[t]i=1∑nj=1∑m[(i,j)=t]
=
∏
t
=
1
min
{
n
,
m
}
f
[
t
]
∑
i
=
1
⌊
n
t
⌋
∑
j
=
1
⌊
m
t
⌋
[
(
i
,
j
)
=
1
]
= \prod\limits_{t = 1}^{\min\{n, m\}} f[t] ^{\sum \limits_{i = 1}^{\lfloor \frac{n}{t} \rfloor} \sum \limits_{j = 1}^{\lfloor \frac{m}{t}\rfloor} [(i, j) = 1]}
=t=1∏min{n,m}f[t]i=1∑⌊tn⌋j=1∑⌊tm⌋[(i,j)=1]
=
∏
t
=
1
min
{
n
,
m
}
f
[
t
]
∑
i
=
1
⌊
n
t
⌋
∑
j
=
1
⌊
m
t
⌋
∑
d
∣
(
i
,
j
)
μ
(
d
)
= \prod \limits_{t = 1}^{\min\{n, m\}} f[t] ^ {\sum \limits_{i = 1}^{\lfloor \frac{n}{t} \rfloor}\sum\limits_{j = 1}^{\lfloor \frac{m}{t} \rfloor} \sum\limits_{d | (i, j)} \mu(d)}
=t=1∏min{n,m}f[t]i=1∑⌊tn⌋j=1∑⌊tm⌋d∣(i,j)∑μ(d)
=
∏
t
=
1
min
{
n
,
m
}
f
[
t
]
∑
d
=
1
⌊
min
{
n
,
m
}
t
⌋
μ
(
d
)
⌊
n
t
d
⌋
⌊
m
t
d
⌋
= \prod \limits_{t = 1}^{\min\{n, m\}} f[t] ^{\sum\limits_{d = 1}^{\lfloor \frac{\min\{n, m\}}{t}\rfloor}\mu(d)\lfloor\frac{n}{td}\rfloor \lfloor \frac{m}{td}\rfloor}
=t=1∏min{n,m}f[t]d=1∑⌊tmin{n,m}⌋μ(d)⌊tdn⌋⌊tdm⌋
考虑枚举
T
=
t
d
T = td
T=td,
=
∏
t
=
1
min
{
n
,
m
}
f
[
t
]
∑
t
∣
T
μ
(
T
t
)
⌊
n
T
⌋
⌊
m
T
⌋
= \prod \limits_{t = 1}^{\min\{n, m\}} f[t] ^{\sum \limits_{t | T} \mu(\frac{T}{t})\lfloor \frac{n}{T} \rfloor \lfloor \frac{m}{T} \rfloor}
=t=1∏min{n,m}f[t]t∣T∑μ(tT)⌊Tn⌋⌊Tm⌋
预处理
μ
(
x
)
,
f
(
x
)
\mu(x), f(x)
μ(x),f(x),直接计算上面的式子,即可做到每组数据
O
(
n
log
n
)
O(n \log n)
O(nlogn) 的复杂度,可通过 60% 的数据。
考虑把
T
T
T 提到最外面,与
n
,
m
n, m
n,m 无关的项提出来预处理,
=
∏
T
=
1
min
{
n
,
m
}
(
∏
t
∣
T
f
[
t
]
μ
(
T
t
)
)
⌊
n
T
⌋
⌊
m
T
⌋
= \prod \limits_{T = 1}^{\min\{n, m\}}(\prod \limits_{t | T}f[t]^{\mu(\frac{T}{t})})^{\lfloor \frac{n}{T} \rfloor \lfloor \frac{m}{T} \rfloor}
=T=1∏min{n,m}(t∣T∏f[t]μ(tT))⌊Tn⌋⌊Tm⌋
设
g
[
T
]
=
∏
t
∣
T
f
[
t
]
μ
(
T
t
)
g[T] = \prod \limits_{t | T}f[t]^{\mu(\frac{T}{t})}
g[T]=t∣T∏f[t]μ(tT),因为
μ
\mu
μ 的取值只有
−
1
,
0
,
1
-1, 0, 1
−1,0,1,预处理
f
f
f 的逆元即可做到
O
(
n
log
n
)
O(n \log n)
O(nlogn) 预处理出
g
g
g。
每组数据对
T
T
T 整除分块,预处理
g
g
g 的前缀积及其逆元,并根据欧拉定理对指数模
(
1
0
9
+
6
)
(10^9 + 6)
(109+6) 减小常数,即可做到每组数据
O
(
n
log
(
1
0
9
+
5
)
)
O(\sqrt{n} \log(10^9 + 5))
O(nlog(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');}}