抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

n(2n4106)n\,(2\le n\le 4\cdot 10^6) 个节点,编号 1n1\sim n,你一开始在节点 nn,想要到节点 11。假设你现在在节点 xx,你可以进行以下两种操作:

  1. 选择一个正整数 y[1,x1]y\in \left[1, x - 1\right],并移动到节点 xyx-y
  2. 选择一个正整数 z[2,x]z\in \left[2, x\right],并移动到节点 xz\left\lfloor\frac{x}{z}\right\rfloor

求有多少种方案到达节点 11,只要有一次选择的 xxzz 不同就算方案不同。答案对 mm 取模,其中 m(108,109)m\in \left(10^8, 10^9\right)mm 是素数。

fif_i 表示 n=in=i 时的答案,我们有:

fi=j=1i1fj+d=2ifidf_i=\sum_{j=1}^{i-1}f_j+\sum_{d=2}^{i}f_{\left\lfloor\frac{i}{d}\right\rfloor}

前一部分表示用减法,后一部分表示用除法。

考虑优化,第一部分直接前缀和,我们直接考虑第二部分。一种很直接的优化是将小于 i\sqrt{i}dd 直接拿出来算,大于 i\sqrt{i}dd 拿出来算贡献, fkf_{k} 能转移到 fif_idd 应该满足 kid<k+1k\le \frac{i}{d} < k + 1,也即 ik+1<dik\frac{i}{k+1}<d\le\frac{i}{k},于是 fkf_kfif_i 的贡献应该为 nknk+1\left\lfloor\frac{n}{k}\right\rfloor-\left\lfloor\frac{n}{k+1}\right\rfloor。这样做复杂度是 O(nn)\mathcal{O}(n\sqrt{n}),过不去,但是如果你打 Div. 2 的话就能过一个 easy 版

我们考虑换一种方式,考虑 fif_i 转移到 fi+1f_{i+1},我们比较 d=2ifid\sum_{d=2}^{i}f_{\left\lfloor\frac{i}{d}\right\rfloor}d=2i+1fi+1d\sum_{d=2}^{i+1}f_{\left\lfloor\frac{i+1}{d}\right\rfloor},有如下变化:

  1. 多了一个 f1f_1,因为 dd 可以等于 i+1i+1
  2. 对于所有 di+1d\mid i+1i+1d=id+1\left\lfloor\frac{i+1}{d}\right\rfloor=\left\lfloor\frac{i}{d}\right\rfloor+1,所以 fi+1f_{i+1}fif_i 多了一个 fi+1df_{\left\lfloor\frac{i+1}{d}\right\rfloor},少了一个 fidf_{\left\lfloor\frac{i}{d}\right\rfloor}

也就是说:

fi+1=j=1ifj+d=2i+1fi+1d=fi+j=1i1fj+d=2i+1fi+1d=fi+fi+f1+di+1(fi+1dfid)=2fi+f1+di+1(fi+1dfid)\begin{aligned} f_{i+1}&=\sum_{j=1}^{i}f_j+\sum_{d=2}^{i+1}f_{\left\lfloor\frac{i+1}{d}\right\rfloor}\\&=f_i+\sum_{j=1}^{i-1}f_j+\sum_{d=2}^{i+1}f_{\left\lfloor\frac{i+1}{d}\right\rfloor}\\&=f_i+f_i+f_1+\sum_{d\mid i+1}\left(f_{\left\lfloor\frac{i+1}{d}\right\rfloor}-f_{\left\lfloor\frac{i}{d}\right\rfloor}\right)\\&=2f_i+f_1+\sum_{d\mid i+1}\left(f_{\left\lfloor\frac{i+1}{d}\right\rfloor}-f_{\left\lfloor\frac{i}{d}\right\rfloor}\right) \end{aligned}

我们发现对于所有 ii,总的约数个数为 i=1nni=O(nlogn)\sum_{i=1}^n\frac{n}{i}=\mathcal{O}(n\log n)。其余转移为 O(n)\mathcal{O}(n),故总复杂度为 O(nlogn)\mathcal{O}(n\log n)

考虑实现,在每次计算出 fif_{i} 的时候,将所有的 fkif_{ki} 都加上 fifi1f_i-f_{i-1},这样空间复杂度就是 O(n)\mathcal{O}(n)

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
const int maxn = 4000005;

int n, mod;

void add(int& x, int y) {
x += y;
if (x >= mod) {
x -= mod;
} else if (x < 0) {
x += mod;
}
}

int f[maxn];

int main() {
read(n), read(mod);
f[1] = 1;
for (int i = 2; i <= n; ++i) {
int tmp = f[i - 1] << 1 | 1;
if (tmp >= mod) {
tmp -= mod;
}
add(f[i], tmp);
if (i == 2) {
f[i] = 2;
}
for (int j = i << 1; j <= n; j += i) {
add(f[j], f[i]);
add(f[j], -f[i - 1]);
}
}
writeln(f[n]);
return 0;
}

评论