Description
定义:
f
(
x
)
=
∑
d
∣
n
∣
μ
(
d
)
∣
f(x)=\sum_{d|n}|\mu(d)|
f(x)=d∣n∑∣μ(d)∣
F
(
n
,
m
)
=
∑
i
=
1
m
f
(
i
n
)
F(n,m)=\sum_{i=1}^mf(in)
F(n,m)=i=1∑mf(in)
答案要求
A
n
s
=
F
(
n
,
m
)
Ans=F(n,m)
Ans=F(n,m)
n
,
m
≤
1
0
7
n,m\leq10^7
n,m≤107
Solution
显然的,
f
(
x
)
f(x)
f(x)是一个积性函数,即
f
(
x
y
)
=
f
(
x
)
f
(
y
)
,
当
gcd
(
x
,
y
)
=
1
f(xy)=f(x)f(y),当\gcd(x,y)=1
f(xy)=f(x)f(y),当gcd(x,y)=1,
又有
f
(
n
i
)
=
f
(
n
)
f
(
i
)
/
f
(
gcd
(
n
,
i
)
)
f(ni)=f(n)f(i)/f(\gcd(n,i))
f(ni)=f(n)f(i)/f(gcd(n,i))
可以将上试改写:
f
(
n
i
)
=
f
(
n
)
f
(
i
)
/
f
(
gcd
(
i
,
n
)
)
=
f
(
n
)
f
(
i
)
∗
∑
T
∣
n
,
T
∣
i
1
f
(
T
)
∑
T
d
∣
n
,
T
d
∣
i
μ
(
d
)
f(ni)=f(n)f(i)/f(\gcd(i,n))=f(n)f(i)*\sum_{T|n,T|i}\frac{1}{f(T)}\sum_{Td|{n,Td|i}}\mu(d)
f(ni)=f(n)f(i)/f(gcd(i,n))=f(n)f(i)∗T∣n,T∣i∑f(T)1Td∣n,Td∣i∑μ(d)
所以
f
(
n
i
)
=
f
(
n
)
f
(
i
)
∗
∑
T
∣
n
,
T
∣
i
∑
d
∣
T
1
f
(
d
)
μ
(
T
d
)
f(ni)=f(n)f(i)*\sum_{T|n,T|i}\sum_{d|T}\frac{1}{f(d)}\mu(\frac{T}{d})
f(ni)=f(n)f(i)∗T∣n,T∣i∑d∣T∑f(d)1μ(dT)
设
g
(
n
)
=
∑
d
∣
n
1
f
(
d
)
μ
(
n
d
)
g(n)=\sum_{d|n}\frac{1}{f(d)}\mu(\frac{n}{d})
g(n)=∑d∣nf(d)1μ(dn)
所以
f
(
n
i
)
=
f
(
n
)
f
(
i
)
∗
∑
T
∣
n
,
T
∣
i
g
(
T
)
f(ni)=f(n)f(i)*\sum_{T|n,T|i}g(T)
f(ni)=f(n)f(i)∗T∣n,T∣i∑g(T)
所以
A
n
s
=
f
(
n
)
∑
d
∣
n
g
(
d
)
∑
i
=
1
⌊
m
d
⌋
f
(
i
d
)
=
f
(
n
)
∑
d
∣
n
g
(
d
)
F
(
d
,
⌊
m
d
⌋
)
Ans=f(n)\sum_{d|n}g(d)\sum_{i=1}^{\lfloor\frac{m}{d}\rfloor}f(id)=f(n)\sum_{d|n}g(d)F(d,\lfloor\frac{m}{d}\rfloor)
Ans=f(n)d∣n∑g(d)i=1∑⌊dm⌋f(id)=f(n)d∣n∑g(d)F(d,⌊dm⌋)
对于 g ( 1... n ) g(1...n) g(1...n),我们可以在 O ( n log ( n ) ) O(n\log(n)) O(nlog(n))的时间内全部算出,
现在问题就变成了如果快速求 F ( d , ⌊ m d ⌋ ) F(d,\lfloor\frac{m}{d}\rfloor) F(d,⌊dm⌋),
我们考虑对于一组数据,最暴力的求法复杂度是多少(即暴力循环求和):
∑
d
=
1
n
⌊
m
d
⌋
≤
1
0
7
log
(
1
0
7
)
\sum_{d=1}^n\lfloor\frac{m}{d}\rfloor \leq10^7\log(10^7)
∑d=1n⌊dm⌋≤107log(107)
所有我们可以将多组询问中所有的
F
(
d
,
⌊
m
d
⌋
)
F(d,\lfloor\frac{m}{d}\rfloor)
F(d,⌊dm⌋)全部离线,只用
O
(
n
log
(
n
)
)
O(n\log(n))
O(nlog(n))的时间便可以全部求出来,
总复杂度: O ( n log ( n ) + ∑ D ( n ) ) O(n\log(n)+\sum D(n)) O(nlog(n)+∑D(n))( D ( n ) D(n) D(n)表示n的约数个数)
Code
#include <bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
typedef long long LL;
const int N=1000500,M=10000500,mo=1e9+7;
int read(int &n)
{
bool q=0;n=0;char ch=' ';
for(;ch!='-'&&(ch<'0'||ch>'9');ch=getchar());
if(ch=='-')ch=getchar(),q=1;
for(;ch<='9'&&ch>='0';ch=getchar())n=(n<<1)+(n<<3)+ch-48;
return q?n=-n:n;
}
int n,m,ans;
int pr[N],mu[M];
bool prz[M];
int f[M],g[M];
int er[101],er1[101];
LL Ans[N];
int a[N];
struct qqww
{
int d,i,m;
}d[N*3];
int d0;
LL ksm(LL q,int w)
{
LL ans=1;
for(;w;w>>=1,q=q*q%mo)if(w&1)ans=ans*q%mo;
return ans;
}
void Pre(int n)
{
mu[1]=1;
fo(i,2,n)
{
if(!prz[i])pr[++pr[0]]=i,mu[i]=-1,f[i]=1;
fo(j,1,pr[0])
{
int t=pr[j]*i;
if(t>n)break;
prz[t]=1;
f[t]=f[i];
if(i%pr[j]==0)break;
f[t]=f[i]+1,mu[t]=-mu[i];
}
}
}
bool PX(qqww q,qqww w){return q.d<w.d||(q.d==w.d&&q.m<w.m);}
int main()
{
int q,w,_;
int SRT=clock();
q=100;
er[0]=1;fo(i,1,q)((er[i]=er[i-1]<<1)>=mo?er[i]-=mo:0);
er1[q]=ksm(er[q],mo-2);
fod(i,q-1,0)((er1[i]=er1[i+1]<<1)>=mo?er1[i]-=mo:0);
Pre(1e7);
int mx=0;
read(_);
fo(I,1,_)
{
a[I]=read(n),read(m);
mx=max(n,mx);
mx=max(m,mx);
for(int i=1;i*i<=n;++i)if(n%i==0)
{
d[++d0].d=i;
d[d0].m=m/i;
d[d0].i=I;
if(i*i==n)continue;
d[++d0].d=n/i;
d[d0].m=m/(n/i);
d[d0].i=I;
}
}
// cerr<<clock()-SRT<<endl;
fo(i,1,mx)if(mu[i])
{
if(mu[i]<0)
{
for(int j=1,k=i;k<=mx;++j,k+=i)((g[k]-=er1[f[j]])<0?g[k]+=mo:0);
}else {
for(int j=1,k=i;k<=mx;++j,k+=i)((g[k]+=er1[f[j]])>=mo?g[k]-=mo:0);
}
}
fo(i,1,mx)f[i]=er[f[i]];
sort(d+1,d+1+d0,PX);
LL t=0,j=1;
// cerr<<clock()-SRT<<endl;
fo(I,1,d0)
{
if(d[I].d!=d[I-1].d)t=0,j=1;
for(;j<=d[I].m;++j)
{
(t+=f[j*d[I].d])>=mo?t-=mo:0;
}
Ans[d[I].i]=(Ans[d[I].i]+t*g[d[I].d])%mo;
}
fo(i,1,_)printf("%lld\n",(Ans[i]*f[a[i]])%mo);
// cerr<<clock()-SRT<<endl;
return 0;
}