牛客练习赛69 F-解方程

    科技2022-07-11  117

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

    题意思路Code(477MS) 传送门: 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; }
    Processed: 0.035, SQL: 8