牛客练习赛69 F-解方程

牛客练习赛69 F-解方程 莫比乌斯反演 + 质因子分解


传送门: https://ac.nowcoder.com/acm/contest/7329/F

题意

求解: f i      m o d      998244353      ( 1 ≤ i ≤ n ) f_i\;\;mod\;\;998244353\;\;(1\leq i\leq n) fimod998244353(1in)

思路

前 置 技 能 : μ ∗ I = ε          σ q = i d q ∗ I          F ( n ) = ∑ d ∣ n μ ( i ) f ( n d ) \red{前置技能:\mu*I =\varepsilon \;\;\;\;\sigma _q=id_q*I\;\;\;\;F(n)=\sum_{d|n}\mu(i)f(\frac{n}{d})} μI=εσq=idqIF(n)=dnμ(i)f(dn)

∑ i ∣ n f ( i ) σ p ( n i ) = σ q ( n )      − >      ( f ∗ σ p ) n = σ q ( n ) \sum_{i|n}f(i)\sigma _p(\frac{n}{i})=\sigma _q(n)\;\;->\;\;(f*\sigma_p )n=\sigma _q(n) inf(i)σp(in)=σq(n)>(fσp)n=σq(n)

先 将 σ 分 解 : 先将\sigma 分解: σ

( f ∗ i d p ∗ I ) n = ( i d q ∗ I ) n (f*id_p*I)n=(id_q*I)n (fidpI)n=(idqI)n

左 右 都 乘 上 μ : 左右都乘上\mu: μ:

( f ∗ i d p ) n = i d q ( n ) (f*id_p)n=id_q(n) (fidp)n=idq(n)

∑ i ∣ n f ( i ) n p i p = n q \sum_{i|n}f(i)\frac{n^p}{i^p}=n^q inf(i)ipnp=nq

∑ i ∣ n f ( i ) i p = n q − p = i d q − p ( n ) \sum_{i|n}\frac{f(i)}{i^p}=n^{q-p}=id_{q-p}(n) inipf(i)=nqp=idqp(n)

反 演 得 : 反演得:

f ( n ) n p = ∑ i ∣ n μ ( i ) ∗ n q − p i q − p \frac{f(n)}{n^p}=\sum_{i|n}\frac{\mu(i)*n^{q-p}}{i^{q-p}} npf(n)=iniqpμ(i)nqp

f ( n ) n q = ∑ i ∣ n μ ( i ) i q − p \frac{f(n)}{n^q}=\sum_{i|n}\frac{\mu(i)}{i^{q-p}} nqf(n)=iniqpμ(i)

因为积性函数卷积性函数之后还是积性函数,所以能得到 f ( n ) n q \frac{f(n)}{n^q} nqf(n)是积性函数。我们考虑与n互质的d,计算 f ( d k ) f(d^k) f(dk)并且由莫比乌斯函数的性质得:

f ( d k ) d k q = 1 − [ k ≠ 0 ] d q − p \frac{f(d^k)}{d^{kq}}=1-\frac{[k\ne 0]}{d^{q-p}} dkqf(dk)=1dqp[k=0]
( 根 据 上 式 , 只 有 i = 1 或 d 时 才 μ ( i ) 满 足 , 其 他 都 是 0 ) (根据上式,只有i=1或d时才\mu(i)满足,其他都是0) (i=1dμ(i)0)

所 以 再 来 看 n , 由 基 本 算 数 定 理 得 : n = p 1 k 1 p 2 k 2 . . . p m k m , 即 : 所以再来看n,由基本算数定理得:n=p_1^{k_1}p_2^{k_2}...p_m^{k_m},即: nn=p1k1p2k2...pmkm

f ( n ) n q = f ( p 1 k 1 ) p 1 q k 1 f ( p 2 k 2 ) p 2 q k 2 . . . f ( p m k m ) p m q k m \frac{f(n)}{n^q}=\frac{f(p_1^{k_1})}{p_1^{qk_1}}\frac{f(p_2^{k_2})}{p_2^{qk_2}}...\frac{f(p_m^{k_m})}{p_m^{qk_m}} nqf(n)=p1qk1f(p1k1)p2qk2f(p2k2)...pmqkmf(pmkm)

f ( n ) n q = ∏ d ∣ n & & d    i s    a    p r i m e ( 1 − 1 d q − p ) \frac{f(n)}{n^q}=\prod_{d|n \&\&d\;is\;a\;prime}(1-\frac{1}{d^{q-p}}) nqf(n)=dn&&disaprime(1dqp1)

提前用欧拉筛处理 f ( p k ) f(p^k) f(pk)即可,注意g数组的含义,因为当 i i%prime[j]=0 i时, p r i m e [ j ] prime[j] prime[j]已经是 p r i m e [ j ] ∗ i prime[j]*i prime[j]i的因子的,而 f [ i ] f[i] f[i] f [ i ∗ p r i m e [ j ] ] f[i*prime[j]] f[iprime[j]]两者之间的区别就是 p r i m e [ j ] q prime[j]^q prime[j]q,这还是比较难想到的。

Code(477MS)


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;

#define INF 0x7f7f7f
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)

const ll mod = 998244353;
// const ll P = 1e9 + 7;
// const double eps = 1e-6;
// const double pi = acos(-1);

const int N = 1e7 + 10;

ll quick_pow(ll a, ll b) {
    ll ans = 1;
    while(b) {
        if(b & 1) ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans % mod;
}

int prime[N];
bool is_prime[N];
int cnt;

ll q, p, n;
ll f[N], g[N];

void Eluer() {
    is_prime[1] = is_prime[0] = true;
    f[1] = 1;
    for(int i = 2;i < N; i++) {
        if(!is_prime[i]) {
            prime[cnt++] = i;
            g[i] = quick_pow(i, q);
            f[i] = (g[i] - quick_pow(i, p)) % mod;
        }
        for(int j = 0;j < cnt && prime[j] * i < N; j++) {
            is_prime[i * prime[j]] = true;
            if(i % prime[j] == 0) {
                f[i * prime[j]] = f[i] * g[prime[j]] % mod;
                break;
            }
            f[i * prime[j]] = f[i] * f[prime[j]] % mod;
        }
    }
}


void solve() {
    cin >> n >> p >> q;
    Eluer();
    ll ans = 0;
    for(int i = 1;i <= n; i++) {
        f[i] = (f[i] % mod + mod) % mod;
        ans ^= f[i];
    }
    cout << ans << endl;
}

signed main() {
    ios_base::sync_with_stdio(false);
    //cin.tie(nullptr);
    //cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值