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=LHa2=LH...an=LH[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=LHa2=LH...an=LH[gcd(a1,a2,...,an)=k]=a1=LHa2=LH...an=LH[gcd(ka1,ka2,...,kan)=1]=a1=kLkHa2=kLkH...an=kLkH[gcd(a1,a2,...,an)=1]=a1=kLkHa2=kLkH...an=kLkHdgcd(a1,a2,...,an)μ(d)=d=1kHμ(d)a1=dkLdkHa2=dkLdkH...an=dkLdkH1=d=1kHμ(d)(dkHdkL1)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=1nf(i)i=1n(fg)(i)=i=1ndig(d)f(di)=d=1ndig(d)f(di)=d=1ng(d)i=1dnf(i)=d=1ng(d)S(dn)g(1)=1S(n)=i=1n(fg)(i)d=2ng(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=1kHμ(i)=i=1nμ(i)μ1=e,S(n)=i=1ne(i)d=2ng(d)S(dn)=1d=2nS(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;
}