P3172 [CQOI2015]选数(莫比乌斯反演+杜教筛)
P3172 [CQOI2015]选数
题意
给定区间[L,H],区间内n个数的最大公约数为k的方案书有多少个。即求
∑ a 1 = L H ∑ a 2 = L H . . . ∑ a n = L H [ g c d ( a 1 , a 2 , . . . , a n ) = k ] \sum_{a_1=L}^H\sum_{a_2=L}^H...\sum_{a_n=L}^H[gcd(a_1,a_2,...,a_n)=k] a1=L∑Ha2=L∑H...an=L∑H[gcd(a1,a2,...,an)=k]
Solution
∑ a 1 = L H ∑ a 2 = L H . . . ∑ a n = L H [ g c d ( a 1 , a 2 , . . . , a n ) = k ] = ∑ a 1 = L H ∑ a 2 = L H . . . ∑ a n = L H [ g c d ( a 1 k , a 2 k , . . . , a n k ) = 1 ] = ∑ a 1 = ⌈ L k ⌉ ⌊ H k ⌋ ∑ a 2 = ⌈ L k ⌉ ⌊ H k ⌋ . . . ∑ a n = ⌈ L k ⌉ ⌊ H k ⌋ [ g c d ( a 1 , a 2 , . . . , a n ) = 1 ] = ∑ a 1 = ⌈ L k ⌉ ⌊ H k ⌋ ∑ a 2 = ⌈ L k ⌉ ⌊ H k ⌋ . . . ∑ a n = ⌈ L k ⌉ ⌊ H k ⌋ ∑ d ∣ g c d ( a 1 , a 2 , . . . , a n ) μ ( d ) = ∑ d = 1 ⌊ H k ⌋ μ ( d ) ∑ a 1 = ⌈ L d k ⌉ ⌊ H d k ⌋ ∑ a 2 = ⌈ L d k ⌉ ⌊ H d k ⌋ . . . ∑ a n = ⌈ L d k ⌉ ⌊ H d k ⌋ 1 = ∑ d = 1 ⌊ H k ⌋ μ ( d ) ( ⌊ H d k ⌋ − ⌊ L − 1 d k ⌋ ) n \sum_{a_1=L}^H\sum_{a_2=L}^H...\sum_{a_n=L}^H[gcd(a_1,a_2,...,a_n)=k] \\=\sum_{a_1=L}^H\sum_{a_2=L}^H...\sum_{a_n=L}^H[gcd(\frac{a_1}{k},\frac{a_2}{k},...,\frac{a_n}{k})=1] \\ =\sum_{a_1=\lceil\frac{L}{k}\rceil}^{\lfloor\frac{H}{k}\rfloor}\sum_{a_2=\lceil\frac{L}{k}\rceil}^{\lfloor\frac{H}{k}\rfloor}...\sum_{a_n=\lceil\frac{L}{k}\rceil}^{\lfloor\frac{H}{k}\rfloor}[gcd(a_1,a_2,...,a_n)=1] \\ =\sum_{a_1=\lceil\frac{L}{k}\rceil}^{\lfloor\frac{H}{k}\rfloor}\sum_{a_2=\lceil\frac{L}{k}\rceil}^{\lfloor\frac{H}{k}\rfloor}...\sum_{a_n=\lceil\frac{L}{k}\rceil}^{\lfloor\frac{H}{k}\rfloor}\sum_{d|gcd(a_1,a_2,...,a_n)}\mu(d) \\ =\sum_{d=1}^{\lfloor\frac{H}{k}\rfloor}\mu(d)\sum_{a_1=\lceil\frac{L}{dk}\rceil}^{\lfloor\frac{H}{dk}\rfloor}\sum_{a_2=\lceil\frac{L}{dk}\rceil}^{\lfloor\frac{H}{dk}\rfloor}...\sum_{a_n=\lceil\frac{L}{dk}\rceil}^{\lfloor\frac{H}{dk}\rfloor}1 \\ =\sum_{d=1}^{\lfloor\frac{H}{k}\rfloor}\mu(d)(\lfloor\frac{H}{dk}\rfloor-\lfloor\frac{L-1}{dk}\rfloor)^n a1=L∑Ha2=L∑H...an=L∑H[gcd(a1,a2,...,an)=k]=a1=L∑Ha2=L∑H...an=L∑H[gcd(ka1,ka2,...,kan)=1]=a1=⌈kL⌉∑⌊kH⌋a2=⌈kL⌉∑⌊kH⌋...an=⌈kL⌉∑⌊kH⌋[gcd(a1,a2,...,an)=1]=a1=⌈kL⌉∑⌊kH⌋a2=⌈kL⌉∑⌊kH⌋...an=⌈kL⌉∑⌊kH⌋d∣gcd(a1,a2,...,an)∑μ(d)=d=1∑⌊kH⌋μ(d)a1=⌈dkL⌉∑⌊dkH⌋a2=⌈dkL⌉∑⌊dkH⌋...an=⌈dkL⌉∑⌊dkH⌋1=d=1∑⌊kH⌋μ(d)(⌊dkH⌋−⌊dkL−1⌋)n
杜教筛求前缀和:
S ( n ) = ∑ i = 1 n f ( i ) ∑ i = 1 n ( f ∗ g ) ( i ) = ∑ i = 1 n ∑ d ∣ i g ( d ) ∗ f ( i d ) = ∑ d = 1 n ∑ d ∣ i g ( d ) ∗ f ( i d ) = ∑ d = 1 n g ( d ) ∑ i = 1 ⌊ n d ⌋ f ( i ) = ∑ d = 1 n g ( d ) S ( ⌊ n d ⌋ ) 根 据 积 性 函 数 g ( 1 ) = 1 S ( n ) = ∑ i = 1 n ( f ∗ g ) ( i ) − ∑ d = 2 n g ( d ) S ( ⌊ n d ⌋ ) S(n)=\sum_{i=1}^nf(i) \\ \sum_{i=1}^n(f*g)(i)=\sum_{i=1}^n\sum_{d|i}g(d)*f(\frac{i}{d}) \\ =\sum_{d=1}^n\sum_{d|i}g(d)*f(\frac{i}{d}) \\ =\sum_{d=1}^ng(d)\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}f(i) \\ =\sum_{d=1}^ng(d)S(\lfloor\frac{n}{d}\rfloor) \\ 根据积性函数g(1)=1 \\S(n) = \sum_{i=1}^n(f*g)(i)-\sum_{d=2}^ng(d)S(\lfloor\frac{n}{d}\rfloor) S(n)=i=1∑nf(i)i=1∑n(f∗g)(i)=i=1∑nd∣i∑g(d)∗f(di)=d=1∑nd∣i∑g(d)∗f(di)=d=1∑ng(d)i=1∑⌊dn⌋f(i)=d=1∑ng(d)S(⌊dn⌋)根据积性函数g(1)=1S(n)=i=1∑n(f∗g)(i)−d=2∑ng(d)S(⌊dn⌋)
记 n = ⌊ H k ⌋ n=\lfloor\frac{H}{k}\rfloor n=⌊kH⌋,那么
S ( n ) = ∑ i = 1 ⌊ H k ⌋ μ ( i ) = ∑ i = 1 n μ ( i ) 根 据 μ ∗ 1 = e , S ( n ) = ∑ i = 1 n e ( i ) − ∑ d = 2 n g ( d ) S ( ⌊ n d ⌋ ) = 1 − ∑ d = 2 n S ( ⌊ n d ⌋ ) S(n)=\sum_{i=1}^{\lfloor\frac{H}{k}\rfloor}\mu(i)=\sum_{i=1}^{n}\mu(i) \\ 根据\mu*1=e,S(n)=\sum_{i=1}^ne(i)-\sum_{d=2}^ng(d)S(\lfloor\frac{n}{d}\rfloor) \\ =1-\sum_{d=2}^nS(\lfloor\frac{n}{d}\rfloor) S(n)=i=1∑⌊kH⌋μ(i)=i=1∑nμ(i)根据μ∗1=e,S(n)=i=1∑ne(i)−d=2∑ng(d)S(⌊dn⌋)=1−d=2∑nS(⌊dn⌋)
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
unordered_map<ll,ll>mpsu;
const int mod=1e9+7;
const int N=1e6;
int prime[N+5],notprime[N+5],cnt=0;
int mu[N+5],smu[N+5];
void initMu()
{
mu[1]=1;
for(int i=2;i<=N;i++)
{
if(!notprime[i])
{
mu[i]=-1;
prime[cnt++]=i;
}
for(int j=0;j<cnt&&1ll*i*prime[j]<=N;j++)
{
notprime[i*prime[j]]=1;
if(i%prime[j])mu[i*prime[j]]=-mu[i];
else {
mu[i*prime[j]]=0;break;}
}
}
for(int i=1;i<=N;i++)smu[i]=smu[i-1]+mu[i];
}
ll fpow(ll x,int power)
{
ll ans=1;
while(power)
{
if(power&1)ans=ans*x%mod;
power>>=1;
x=x*x%mod;
}
return ans;
}
ll getSmu(ll x)
{
if(x<=N)return smu[x];
if(mpsu[x]!=0)return mpsu[x];
ll ans=1;
for(int l=2,r;l>=0&&l<=x;l=r+1)
{
r=x/(x/l);
ans=(ans-1ll*getSmu(x/l)*(r-l+1)%mod)%mod;
}
return mpsu[x]=(ans+mod)%mod;
}
int n,k,L,H;
int main()
{
initMu();
scanf("%d%d%d%d",&n,&k,&L,&H);
H=H/k;
L=(L-1)/k;
ll res=0;
for(int l=1,r;l<=H;l=r+1)
{
if(L>=l)
r=min(H/(H/l),L/(L/l));
else
r=H/(H/l);
res=(res+1ll*fpow(H/l-L/l,n)*(getSmu(r)-getSmu(l-1))%mod+mod)%mod;
}
printf("%lld",res);
return 0;
}