n , p , q n,p,q n,p,q 均为 1 0 7 10^7 107,这个规模下可以考虑求出所有的 f ( i ) f(i) f(i),题目给出的式子很明显要用莫比乌斯反演,因为莫比乌斯反演的形式为:
形式一:设 F ( n ) = ∑ d ∣ n f ( d ) F(n) = \displaystyle\sum_{d | n} f(d) F(n)=d∣n∑f(d) ,则有 f ( n ) = ∑ d ∣ n μ ( d ) ∗ F ( n d ) = ∑ d ∣ n F ( d ) ∗ μ ( n d ) f(n) = \displaystyle\sum_{d | n}\mu(d)*F(\frac{n}{d}) = \sum_{d | n}F(d)*\mu(\frac{n}{d}) f(n)=d∣n∑μ(d)∗F(dn)=d∣n∑F(d)∗μ(dn)
形式二:设 F ( n ) = ∑ n ∣ d f ( d ) F(n) = \displaystyle\sum_{n | d} f(d) F(n)=n∣d∑f(d) ,则有 f ( n ) = ∑ n ∣ d F ( d ) ∗ μ ( d n ) f(n) = \displaystyle\sum_{n | d} F(d)*\mu(\frac{d}{n}) f(n)=n∣d∑F(d)∗μ(nd)
接下来开始推公式:
σ ( n ) = ∑ i ∣ n i = ∑ i ∣ n I d ( i ) = ( I d ∗ I ) ( n ) \sigma(n)=\displaystyle\sum_{i|n}i=\sum_{i|n}Id(i)=(Id*I)(n) σ(n)=i∣n∑i=i∣n∑Id(i)=(Id∗I)(n)
显然同样可以得到 σ p ( n ) = ∑ i ∣ n i = ∑ i ∣ n I d p ( i ) = ( I d p ∗ I ) ( n ) \sigma_p(n)=\displaystyle\sum_{i|n}i=\sum_{i|n}Id_p(i)=(Id_p*I)(n) σp(n)=i∣n∑i=i∣n∑Idp(i)=(Idp∗I)(n)
那么有 f ∗ I d p ∗ I = I d q ∗ I f*Id_p*I=Id_q*I f∗Idp∗I=Idq∗I,左右约掉函数 I I I,得到 f ∗ I d p = I d q f*Id_p = Id_q f∗Idp=Idq
∑ i ∣ n f ( i ) ( n i ) p = n q \sum_{i|n}f(i)(\frac{n}{i})^p=n^q i∣n∑f(i)(in)p=nq ∑ i ∣ n f ( i ) i p = n q − p \sum_{i|n}\frac{f(i)}{i^p}=n^{q-p} i∣n∑ipf(i)=nq−p
套用莫比乌斯反演可以得到: f ( n ) n p = ∑ i ∣ n μ ( i ) ∗ ( n i ) q − p \frac{f(n)}{n^p}=\sum_{i|n}\mu(i)*(\frac{n}{i})^{q-p} npf(n)=i∣n∑μ(i)∗(in)q−p f ( n ) = n p ∑ i ∣ n μ ( i ) ∗ ( n i ) q − p = n q ∗ ∑ i ∣ n μ ( i ) i q − p f(n)=n^p\sum_{i|n}\mu(i)*(\frac{n}{i})^{q-p}=n^q*\sum_{i|n}\frac{\mu(i)}{i^{q-p}} f(n)=npi∣n∑μ(i)∗(in)q−p=nq∗i∣n∑iq−pμ(i)
迪利克雷卷积的性质告诉我们, f ( n ) n p \frac{f(n)}{n^p} npf(n) 是一个积性函数,且 n p n^p np 是一个积性函数,那么 f ( n ) f(n) f(n) 一定也是一个积性函数,积性函数乘积性函数得到的也是积性函数。
考虑用欧拉筛来筛出 f ( n ) f(n) f(n),考虑 f ( d ) , f ( d k ) f(d),f(d^k) f(d),f(dk)
f ( d ) f(d) f(d) 显然等于 d q ∗ ( 1 − 1 d q − p ) d^q*(1-\displaystyle\frac{1}{d^{q-p}}) dq∗(1−dq−p1)
f ( d k ) = d k q ∗ ( 1 − 1 d q − p ) f(d^k) = d^{k q}*(1-\displaystyle\frac{1}{d^{q-p}}) f(dk)=dkq∗(1−dq−p1)
直接欧拉筛,这里不免要求一下质数的幂次,根据质数的分布性质, n n n 以内大约有 n log n \frac{n}{\log n} lognn 个质数,对这些质数求快速幂的复杂度为 log n \log n logn,时间复杂度为 O ( n log n ∗ log n = n ) O(\frac{n}{\log n} * \log n=n) O(lognn∗logn=n) 的
代码:
#include
using namespace std;
const int maxn = 1e7 + 10;
const int mod = 998244353;
bool ispri[maxn];
int n, p, q, f[maxn], pri[maxn], val[maxn];
int fpow(int a,int b) {
int r = 1;
while (b) {
if (b & 1) r = 1ll * r * a % mod;
b >>= 1;
a = 1ll * a * a % mod;
}
return r;
}
int calc(int d) {
int v = p - q;
if (v < 0) return (1 - fpow(fpow(d,-v),mod - 2) + mod) % mod;
else return (1 - fpow(d,v) + mod) % mod;
}
void sieve(int n) {
ispri[0] = ispri[1] = true; pri[0] = 0; f[1] = 1;
for (int i = 2; i <= n; i++) {
if (!ispri[i]) {
pri[++pri[0]] = i;
val[i] = fpow(i,q);
f[i] = 1ll * val[i] * calc(i) % mod;
}
for (int j = 1; j <= pri[0] && i * pri[j] <= n; j++) {
ispri[i * pri[j]] = true;
if (i % pri[j] == 0) {
f[i * pri[j]] = 1ll * f[i] * val[pri[j]] % mod;
break;
} else {
f[i * pri[j]] = 1ll * f[i] * f[pri[j]] % mod;
}
}
}
/*for (int i = 1; i <= n; i++)
f[i] = 1ll * f[i] * fpow(i,q) % mod; */
}
int main() {
scanf("%d%d%d",&n,&p,&q);
sieve(n);
int res = 0;
for (int i = 1; i <= n; i++)
res = res ^ f[i];
printf("%d\n",res);
return 0;
}