链接 D1. Up the Strip (simplified version)
题意
给出一个n,有两种操作方式
- 从 1 1 1 ~ x − 1 x-1 x−1中选一个数 y y y,从 x x x 位置移动到 x − y x-y x−y 位置;
- 从 2 2 2 ~ x x x中选一个数 y y y,从 x x x 位置移动到 x y \frac{x}{y} yx 位置;
求出 n n n 到 1 1 1 的所有可能数量,并对 m m m 取模;
思路
这是问题的简单版本,D2还没写,先咕着,来了来了D2QWQ;
这种大问题可以化成小问题解决的,我们采用 d p dp dp , d p [ i ] dp[i] dp[i] 表示从 i i i 移动到 1 1 1 的所有可能数量;
对于第一种操作方式,可知
d
p
[
i
]
=
∑
j
=
1
i
−
1
dp[i] = \sum_{j=1}^{i - 1}
dp[i]=∑j=1i−1,这个可以用前缀和优化;
对于第二种操作方式,很显然就是整除分块的板子了,可以去网上看看整除分块的知识点,最简单的整除分块就可以处理这个问题了;
AC代码
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <map>
#include <vector>
#include <queue>
#define x first
#define y second
using namespace std;
typedef long long ll;
const int N = 300010;
int n;
ll m;
ll dp[N];
int main()
{
cin >> n >> m;
ll sum = 0;//前缀和
dp[1] = 1;
for (int i = 2; i <= n; i ++) {
sum += dp[i - 1];
sum %= m;
dp[i] += sum;
for (int l = 2, r; l <= i; l = r + 1) {
r = i / (i / l);
dp[i] += ((r - l + 1) * dp[i / l]);
dp[i] %= m;
}
}
cout << dp[n] << endl;
return 0;
}