题目大意: 求 ∏ i = 1 a ∏ j = 1 b p ( gcd ( i , j ) ) \prod _{i=1}^a \prod _{j=1}^b p(\gcd(i,j)) ∏i=1a∏j=1bp(gcd(i,j)),其中 p p p 是斐波那契数列。
题解
设
s
(
d
)
s(d)
s(d) 表示满足
gcd
(
i
,
j
)
=
d
\gcd(i,j)=d
gcd(i,j)=d 的
i
,
j
i,j
i,j 的数量,
F
(
n
)
F(n)
F(n) 表示满足
n
∣
gcd
(
i
,
j
)
n|\gcd(i,j)
n∣gcd(i,j) 的
i
,
j
i,j
i,j 的数量,那么有:
F
(
n
)
=
∑
n
∣
d
f
(
d
)
F(n)=\sum_{n|d}f(d)
F(n)=n∣d∑f(d)
根据莫比乌斯反演,有:
f
(
d
)
=
∑
d
∣
n
F
(
n
)
μ
(
n
d
)
f(d)=\sum_{d|n}F(n)\mu(\frac nd)
f(d)=d∣n∑F(n)μ(dn)
大力推柿子:
∏
i
=
1
a
∏
j
=
1
b
p
(
gcd
(
i
,
j
)
)
=
∏
i
=
1
min
(
a
,
b
)
p
(
i
)
f
(
i
)
=
∏
i
=
1
min
(
a
,
b
)
p
(
i
)
∑
i
∣
d
F
(
d
)
μ
(
d
i
)
\prod _{i=1}^a \prod _{j=1}^b p(\gcd(i,j))\\ =\prod_{i=1}^{\min(a,b)} p(i)^{f(i)}\\ =\prod_{i=1}^{\min(a,b)} p(i)^{\sum_{i|d}F(d)\mu(\frac d i)}
i=1∏aj=1∏bp(gcd(i,j))=i=1∏min(a,b)p(i)f(i)=i=1∏min(a,b)p(i)∑i∣dF(d)μ(id)
显然有
F
(
n
)
=
⌊
a
n
⌋
⌊
b
n
⌋
F(n)=\lfloor \frac a n \rfloor \lfloor \frac b n \rfloor
F(n)=⌊na⌋⌊nb⌋,带进去得:
=
∏
i
=
1
min
(
a
,
b
)
p
(
i
)
∑
i
∣
d
⌊
a
d
⌋
⌊
b
d
⌋
μ
(
d
i
)
=\prod_{i=1}^{\min(a,b)} p(i)^{\sum_{i|d}\lfloor \frac a d \rfloor \lfloor \frac b d \rfloor\mu(\frac d i)}
=i=1∏min(a,b)p(i)∑i∣d⌊da⌋⌊db⌋μ(id)
设
j
=
d
i
j=\frac d i
j=id,更换枚举对象,于是有:
=
∏
i
=
1
min
(
a
,
b
)
p
(
i
)
∑
j
=
1
min
(
a
,
b
)
i
μ
(
j
)
⌊
a
i
j
⌋
⌊
b
i
j
⌋
=\prod_{i=1}^{\min(a,b)} p(i)^{\sum_{j=1}^{\frac {\min(a,b)} i} \mu(j)\lfloor \frac a {ij} \rfloor \lfloor \frac b {ij} \rfloor}
=i=1∏min(a,b)p(i)∑j=1imin(a,b)μ(j)⌊ija⌋⌊ijb⌋
那个
∑
\sum
∑ 是可以弄出来的,变成一个
∏
\prod
∏
=
∏
i
=
1
min
(
a
,
b
)
∏
j
=
1
min
(
a
,
b
)
i
p
(
i
)
μ
(
j
)
⌊
a
i
j
⌋
⌊
b
i
j
⌋
=\prod_{i=1}^{\min(a,b)}\prod_{j=1}^{\frac {\min(a,b)} i} p(i)^{ \mu(j)\lfloor \frac a {ij} \rfloor \lfloor \frac b {ij} \rfloor}
=i=1∏min(a,b)j=1∏imin(a,b)p(i)μ(j)⌊ija⌋⌊ijb⌋
根据莫比乌斯反演的一般思想: 两个变量乘在一起是很难看的,比如说里面的
i
j
ij
ij,于是用一个
k
k
k 代替掉,更换枚举对象,有
=
∏
k
=
1
min
(
a
,
b
)
∏
j
∣
k
p
(
k
j
)
μ
(
j
)
⌊
a
k
⌋
⌊
b
k
⌋
=
∏
k
=
1
min
(
a
,
b
)
(
∏
j
∣
k
p
(
k
j
)
μ
(
j
)
)
⌊
a
k
⌋
⌊
b
k
⌋
=\prod_{k=1}^{\min(a,b)} \prod_{j|k} p(\frac k j)^{\mu(j)\lfloor \frac a k \rfloor \lfloor \frac b k \rfloor}\\ =\prod_{k=1}^{\min(a,b)} \left(\prod_{j|k} p(\frac k j)^{\mu(j)}\right)^{\lfloor \frac a k \rfloor \lfloor \frac b k \rfloor}\\
=k=1∏min(a,b)j∣k∏p(jk)μ(j)⌊ka⌋⌊kb⌋=k=1∏min(a,b)⎝⎛j∣k∏p(jk)μ(j)⎠⎞⌊ka⌋⌊kb⌋
设
S
(
n
)
=
∏
d
∣
n
p
(
n
d
)
μ
(
d
)
S(n)=\prod_{d|n} p(\frac n d)^{\mu(d)}
S(n)=∏d∣np(dn)μ(d),那么柿子变成:
=
∏
k
=
1
min
(
a
,
b
)
S
(
k
)
⌊
a
k
⌋
⌊
b
k
⌋
=\prod_{k=1}^{\min(a,b)}S(k)^{\lfloor \frac a k \rfloor \lfloor \frac b k \rfloor}\\
=k=1∏min(a,b)S(k)⌊ka⌋⌊kb⌋
因为 μ ( d ) \mu(d) μ(d) 只有三种取值: − 1 , 0 , 1 -1,0,1 −1,0,1 ,所以 S S S 是可以快速地预处理的。
然后除法分块即可。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 1000010
#define ll long long
#define mod 1000000007
int T,n,m;
int prime[maxn],t=0;
bool v[maxn];
int mu[maxn];
ll f[maxn],S[maxn];
ll ksm(ll x,ll y)
{
ll re=1,tot=x;
while(y>0)
{
if(y%2==1)re=re*tot%mod;
tot=tot*tot%mod;
y/=2;
}
return re;
}
ll inv(ll x){return ksm(x,mod-2);}
void work()
{
mu[1]=1;
for(int i=2;i<=maxn-10;i++)//线性筛mu
{
if(!v[i])prime[++t]=i,mu[i]=-1;
for(int j=1;j<=t&&i*prime[j]<=maxn-10;j++)
{
v[i*prime[j]]=true;
if(i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
f[1]=f[2]=1;
S[0]=S[1]=S[2]=1;
for(int i=3;i<=maxn-10;i++)
f[i]=(f[i-1]+f[i-2])%mod,S[i]=1;//预处理斐波那契数列
for(int i=1;i<=maxn-10;i++)
for(int j=i;j<=maxn-10;j+=i)
if(mu[j/i]==-1)S[j]=S[j]*inv(f[i])%mod;
else if(mu[j/i]==1)S[j]=S[j]*f[i]%mod;//处理S
for(int i=1;i<=maxn-10;i++)//求S的前缀积
S[i]=S[i]*S[i-1]%mod;
}
int main()
{
work();
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
int l=1,r;
ll ans=1;
while(l<=min(n,m))
{
r=min(n/(n/l),m/(m/l));
ans=ans*ksm(S[r]*inv(S[l-1])%mod,(ll)(n/l)*(m/l))%mod;
l=r+1;
}
printf("%lld\n",ans);
}
}