链接 D2. Up the Strip
题意
懒得写了,看我的D1博客吧D1
思路
更改一下dp方式, d p [ i ] dp[i] dp[i] 表示从 n n n 到 i i i 有多少种方式,然后从后往前进行遍历更新 d p dp dp 数组;
对于 i i i,然后对于每个除数,例如 2 2 2 ,发现只有 2 i , 2 i + 1 2i,2i+1 2i,2i+1 才能通过除 2 2 2 得到 i i i ,对于3…分析一波发现成块状分布,取那一段的和即可, 用后缀和维护即可;
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;
typedef pair <int,int> PII;
const int N = 4000010;
const ll mod = 998244353;
const double pi = 3.1415926535897932;
int n;
ll m;
ll dp[N], sum[N];
int main()
{
cin >> n >> m;
dp[n] = 1, sum[n] = 1;
for (int i = n - 1; i >= 1; i --) {
dp[i] = sum[i + 1];
for (int j = 2; i * j <= n; j ++) {
int r = min(n, i * j + j - 1);
dp[i] = dp[i] + sum[i * j] - sum[r + 1];
dp[i] += m;
dp[i] %= m;
}
sum[i] = dp[i] + sum[i + 1];
sum[i] %= m;
}
cout << dp[1] << endl;
return 0;
}