【2021 ICPC Gran Premio de Mexico 2da Fecha F】Flipped Factorization 题解

题目大意

  设 $x$ 的质因数分解为 $p_1^{c_1}p_2^{c_2}\cdots p_m^{c_m}$,记 $f(x) = c_1^{p_1}c_2^{p_2}\cdots c_m^{p_m}$,给定 $n$,求 $\sum_{i=1}^n f(n) \bmod 10^9+7$。

  $n \le 10^{14}$
  10s

题解

  $n$ 的这个范围没法筛,但却很根号。
  因此用 powerful number 求积性函数和。

  观察到对质数来说 $f(p)=1$,能对上这个形式的,马上想到全 1 函数 $1(n)=1$。然后观察 $h = \frac{f}{1} = f \ast \mu$,得到

  然后推式子

  又由于 $h$ 只在 powerful number 处有值,因此用 dfs 把 $O(\sqrt n)$ 个 powerful number 都找出来算答案就行了。dfs 的过程中要维护 $h$ 的值,$c^p$ 可以用快速幂算。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include<bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;

typedef long long LL;

const int maxp0=1e7+5;
const LL mo=1e9+7;

LL n;

int p[maxp0],p0;
bool bz[maxp0];
void Prime(int n) {
fo(i,2,n) {
if (!bz[i]) p[++p0]=i;
fo(j,1,p0) {
if (i*p[j]>n) break;
bz[i*p[j]]=1;
if (i%p[j]==0) break;
}
}
}

LL Pow(LL x,LL y) {
LL re=1;
for(; y; y>>=1, x=x*x%mo) if (y&1) re=re*x%mo;
return re;
}

LL ans;
void dfs(int k,LL h,LL i) {
if (k>p0) return;
if (n/i<(LL)p[k]*p[k]) return;
dfs(k+1,h,i);
LL last=1;
i*=p[k];
for(int c=2; ; c++) {
LL cur=Pow(c,p[k]);
LL newh=h*(cur-last+mo)%mo;
i*=p[k];
(ans+=(n/i)%mo*newh)%=mo;
dfs(k+1,newh,i);
if (n/i<p[k]) break;
last=cur;
}
}

int main() {
Prime(1e7);

scanf("%lld",&n);

ans=n%mo;
dfs(1,1,1);

printf("%lld\n",ans);
}