[CQOI2015]选数(数论分块+杜教筛)

problem

洛谷链接

solution

L , H L,H L,H 的范围放缩 1 K \frac 1 K K1,都除掉 K K K,特殊的 L L L 边界注意一下。

H ← H / K , L ← ( L − 1 ) / K + 1 H\leftarrow H/K,L\leftarrow (L-1)/K+1 HH/K,L(L1)/K+1

问题转化为 [ L , H ] [L,H] [L,H] 中任选 N N N 个数 gcd = 1 \text{gcd}=1 gcd=1 的方案数。

T ( i ) : T(i): T(i): [ L , H ] [L,H] [L,H] 中选 N N N 个数 i ∣ gcd i|\text{gcd} igcd 的方案数,即 ( ⌊ H i ⌋ − ⌊ L − 1 i ⌋ ) N (\lfloor\frac H i\rfloor-\lfloor\frac {L-1}i\rfloor)^N (iHiL1)N

t ( i ) : t(i): t(i): [ L , H ] [L,H] [L,H] 中选 N N N 个数 i = gcd i=\text{gcd} i=gcd 的方案数。

根据定义显然有, T ( i ) = ∑ i ∣ d t ( d ) T(i)=\sum_{i|d}t(d) T(i)=idt(d)

莫比乌斯反演得 t ( i ) = ∑ i ∣ d μ ( d i ) T ( d ) t(i)=\sum_{i|d}\mu(\frac{d}{i})T(d) t(i)=idμ(id)T(d)

答案即为 t ( 1 ) = ∑ i = 1 i n f μ ( i ) T ( i ) = ∑ i = 1 i n f μ ( i ) ( ⌊ H i ⌋ − ⌊ L − 1 i ⌋ ) N t(1)=\sum_{i=1}^{inf}\mu(i)T(i)=\sum_{i=1}^{inf}\mu(i)(\lfloor\frac H i\rfloor-\lfloor\frac {L-1}i\rfloor)^N t(1)=i=1infμ(i)T(i)=i=1infμ(i)(iHiL1)N

H , L H,L H,L 非常大,不能直接线筛后整除分块。

但可杜教筛,设定一个阀值 M M M 预处理出 M M M 以内的 μ \mu μ,同样整除分块后杜教筛能做到 O ( H 2 3 ) O(H^{\frac 2 3}) O(H32)

T ( i ) T(i) T(i) 分类,假设 i ∈ [ l , r ] i\in[l,r] i[l,r] T ( i ) T(i) T(i) 都是一样的,那么对 ∑ i = l r μ ( i ) \sum_{i=l}^r\mu(i) i=lrμ(i) 进行杜教筛迅速求和。

∑ i = l r μ ( i ) = ∑ i = 1 r μ ( i ) − ∑ i = 1 l − 1 μ ( i ) \sum_{i=l}^r\mu(i)=\sum_{i=1}^r\mu(i)-\sum_{i=1}^{l-1}\mu(i) i=lrμ(i)=i=1rμ(i)i=1l1μ(i)。这样就化成了标准的杜教筛形式。

∑ μ ( i ) : ϵ = μ ∗ I \sum\mu(i):\epsilon=\mu*I μ(i):ϵ=μI h ↔ ϵ ; f ↔ μ ; g ↔ I h\leftrightarrow \epsilon;f\leftrightarrow \mu;g\leftrightarrow I hϵ;fμ;gI

s ( n ) = ∑ i = 1 n f ( i ) = ∑ i = 1 n μ ( i ) s(n)=\sum_{i=1}^nf(i)=\sum_{i=1}^n\mu(i) s(n)=i=1nf(i)=i=1nμ(i)

g ( 1 ) s ( n ) = ∑ i = 1 n ϵ ( i ) − ∑ i = 2 n g ( i ) s ( ⌊ n i ⌋ ) ⇔ s ( n ) = 1 − ∑ i = 2 n s ( ⌊ n i ⌋ ) g(1)s(n)=\sum_{i=1}^n\epsilon(i)-\sum_{i=2}^ng(i)s(\lfloor\frac n i\rfloor)\Leftrightarrow s(n)=1-\sum_{i=2}^ns(\lfloor\frac n i\rfloor) g(1)s(n)=i=1nϵ(i)i=2ng(i)s(in)s(n)=1i=2ns(in)

s s s 函数进行记忆化递归,以及同样的整除分块。

这样子连 H − L ≤ 1 e 5 H-L\le 1e5 HL1e5 的性质都没有用上!^_^ 这性质好像是拿来容斥递推用的。

一些省掉的推导☞莫比乌斯反演杜教筛

code

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define mod 1000000007
#define maxn 1000005
int mu[maxn], prime[maxn];
bool vis[maxn];
unordered_map < int, int > mp;
int N, M, K, L, H, cnt;

int qkpow( int x, int y ) {
    int ans = 1;
    while( y ) {
        if( y & 1 ) ans = ans * x % mod;
        x = x * x % mod;
        y >>= 1;
    }
    return ans;
}

int solve( int n ) {
    if( n <= M ) return mu[n];
    if( mp.find( n ) != mp.end() ) return mp[n];
    int ans = 1;
    for( int l = 2, r;l <= n;l = r + 1 ) {
        r = n / ( n / l );
        ( ans -= solve( n / l ) * ( r - l + 1 ) ) %= mod;
    }
    return mp[n] = ans;
}

signed main() {
    scanf( "%lld %lld %lld %lld", &N, &K, &L, &H );
    H /= K, L = ( L - 1 ) / K + 1;
    M = min( (int)1e6, H );
    mu[1] = 1; 
    for( int i = 2;i <= M;i ++ ) {
        if( ! vis[i] ) prime[++ cnt] = i, mu[i] = -1;
        for( int j = 1;j <= cnt and i * prime[j] <= M;j ++ ) {
            vis[i * prime[j]] = 1;
            if( i % prime[j] == 0 ) { mu[i * prime[j]] = 0; break; }
            else mu[i * prime[j]] = -mu[i];
        }
    }
    for( int i = 1;i <= M;i ++ ) mu[i] += mu[i - 1];
    L --; int ans = 0;
    for( int l = 1, r;l <= H;l = r + 1 ) {
        if( ! ( L / l ) ) r = H / ( H / l );
        else r = min( H / ( H / l ), L / ( L / l ) );
        ( ans += qkpow( H / l - L / l, N ) * ( solve( r ) - solve( l - 1 ) ) ) %= mod;
    }
    printf( "%lld\n", ( ans + mod ) % mod );
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值