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

题目大意

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

  n1014n \le 10^{14}
  10s

题解

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

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

h(pc)={cp(c1)p,c>10,c=1h(p^c)=\begin{cases} c^p-(c-1)^p, &c>1 \\ 0, &c=1 \end{cases}

  然后推式子

f=h1i=1nf(i)=i=1nj=1nih(i)1(j)=i=1nh(i)ni\begin{aligned} & f = h \ast 1 \\ \Rightarrow & \sum_{i=1}^n f(i) = \sum_{i=1}^n \sum_{j=1}^{\lfloor \frac ni \rfloor} h(i)1(j) = \sum_{i=1}^n h(i) \lfloor \frac ni \rfloor \\ \end{aligned}

  又由于 hh 只在 powerful number 处有值,因此用 dfs 把 O(n)O(\sqrt n) 个 powerful number 都找出来算答案就行了。dfs 的过程中要维护 hh 的值,cpc^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);
}