牛客练习赛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(1≤i≤n)。
思路
前 置 技 能 : μ ∗ 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=idq∗IF(n)=∑d∣nμ(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) i∣n∑f(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 (f∗idp∗I)n=(idq∗I)n
左 右 都 乘 上 μ : 左右都乘上\mu: 左右都乘上μ:
( f ∗ i d p ) n = i d q ( n ) (f*id_p)n=id_q(n) (f∗idp)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 i∣n∑f(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) i∣n∑ipf(i)=nq−p=idq−p(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)=i∣n∑iq−pμ(i)∗nq−p
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)=i∣n∑iq−pμ(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)=1−dq−p[k=0]
(
根
据
上
式
,
只
有
i
=
1
或
d
时
才
μ
(
i
)
满
足
,
其
他
都
是
0
)
(根据上式,只有i=1或d时才\mu(i)满足,其他都是0)
(根据上式,只有i=1或d时才μ(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},即: 所以再来看n,由基本算数定理得:n=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)=d∣n&&disaprime∏(1−dq−p1)
提前用欧拉筛处理 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[i∗prime[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;
}