BZOJ 3601 一个人的数论 (莫比乌斯反演+伯努利数)

题目大意:

在这里插入图片描述
(来源)

解题思路:

∑ i = 1 n [ g c d ( i , n ) = = 1 ] ∗ i d \sum_{i=1}^{n}[gcd(i,n)==1]*i^d i=1n[gcd(i,n)==1]id

= ∑ i = 1 n ε ( g c d ( i , n ) ) ∗ i d =\sum_{i=1}^n\varepsilon (gcd(i,n))*i^d =i=1nε(gcd(i,n))id

= ∑ i = 1 n i d ∑ g ∣ i , g ∣ n μ ( g ) =\sum_{i=1}^ni^d\sum_{g|i,g|n}\mu(g) =i=1nidgi,gnμ(g)

= ∑ g ∣ n μ ( g ) ∑ i = 1 n k ( k i ) d =\sum_{g|n}\mu(g)\sum_{i=1}^{\frac nk}(ki)^d =gnμ(g)i=1kn(ki)d

= ∑ g ∣ n μ ( g ) g d ∑ i = 1 n k i d =\sum_{g|n}\mu(g)g^d\sum_{i=1}^{\frac nk}i^d =gnμ(g)gdi=1knid
由伯努利数
∑ i = 1 n k i d = ∑ i = 1 d + 1 a i ∗ ( n p ) i \sum_{i=1}^{\frac nk}i^d=\sum_{i=1}^{d + 1}a_i*(\frac np)^i i=1knid=i=1d+1ai(pn)i

a i = 1 d + 1 ∗ B d + 1 − i ∗ C d + 1 d + 1 − i a_i=\frac{1}{d+1}*B_{d+1-i}*C_{d+1}^{d+1-i} ai=d+11Bd+1iCd+1d+1i

原式= ∑ i = 1 d + 1 a i ∑ g ∣ n μ ( g ) g d ∗ ( n g ) i \sum_{i=1}^{d+1}a_i\sum_{g|n}\mu(g)g^d*(\frac ng)^i i=1d+1aignμ(g)gd(gn)i

又因为 ∑ g ∣ n μ ( g ) g d ∗ ( n g ) i \sum_{g|n}\mu(g)g^d*(\frac ng)^i gnμ(g)gd(gn)i为积性函数,所以把每个质因子先计算再相乘即可

又对于 n = p c n=p^c n=pc时, ∑ g ∣ n μ ( g ) g d ∗ ( n g ) i = p c i − p c i + d − i \sum_{g|n}\mu(g)g^d*(\frac ng)^i=p^{ci}-p^{ci+d-i} gnμ(g)gd(gn)i=pcipci+di(当且仅当 μ ( 1 ) \mu(1) μ(1) μ ( p ) \mu(p) μ(p)有作用)

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 2e3 + 10;
const ll mod = 1e9 + 7;
ll c[maxn][maxn];
ll b[maxn], inv[maxn];
void init() {
    for (ll i = 0; i < maxn; i++) {
        c[i][0] = c[i][i] = 1;
        for (ll k = 1; k < i; k++)
            c[i][k] = (c[i - 1][k] + c[i - 1][k - 1]) % mod;
    }
    inv[1] = 1;
    for (ll i = 2; i < maxn; i++)
        inv[i] = (mod - mod / i) * inv[mod % i] % mod;
    b[0] = 1;
    for (ll i = 1; i < maxn; i++) {
        ll ans = 0;
        if (i == maxn - 1) break;
        for (ll k = 0; k < i; k++)
            ans = (ans + c[i + 1][k] * b[k]) % mod;
        ans = (ans * (-inv[i + 1]) % mod + mod) % mod;
        b[i] = ans;
    }
}
ll d, w;
ll a[maxn], p[maxn], alp[maxn];
void cal_a() {
    for (ll i = 1; i <= d + 1; i++)
        a[i] = inv[d + 1] * c[d + 1][d + 1 - i] % mod * b[d + 1 - i] % mod;
}
ll qpow(ll a, ll b) {
    ll res = 1;
    while (b) {
        if (b & 1) res = res * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return res;
}
int main() {
    init();
    cin >> d >> w;
    cal_a();
    for (ll i = 1; i <= w; i++)
        cin >> p[i] >> alp[i];
    ll ans = 0;
    for (ll i = 1; i <= d + 1; i++) {
        ll res = a[i] % mod;
        for (ll j = 1; j <= w; j++) {
            ll tmp = ((qpow(p[j], alp[j] * i) - qpow(p[j], d + (alp[j] - 1) * i)) % mod + mod) % mod;
            res = res * tmp % mod; 
        }
        ans = (ans + res) % mod;
    }
    cout << ans << endl;
}

参考博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值