题意:
给正整数 n n n ( n < = 1 e 5 ) (n<=1e5) (n<=1e5) 和 k k k, k k k代表 k k k ( k < = 10 ) (k<=10) (k<=10)个区间,求 1 1 1到 n n n 有多少种方案。
思路:
我们可以发现,第 i i i个点的答案为前 i i i个 1 − i 1-i 1−i区间答案的累加,而现在我们只知道有 k k k个区间可以利用,同理我们类别 1 − i 1-i 1−i的方式取,可用区间的元素来构造答案即可。
参考代码
/*
* @Descripttion: fst
* @version:
* @Author: Vain
* @Date: 2020-08-26 11:58:46
* @LastEditors: sueRimn
* @LastEditTime: 2020-11-02 20:54:09
*/
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
vector<int> f[maxn];
int a[maxn];
int vis[maxn * 5];
void read(ll &v)
{
ll k = 1;
v = 0;
ll c = getchar();
while (c < '0' || c > '9')
{
if (c == '-')
k = 0;
c = getchar();
}
while (c >= '0' && c <= '9')
v = (v << 3) + (v << 1) + (c - 48), c = getchar();
if (k == 0)
v = -v;
}
ll dp[maxn], sum[maxn];
pair<int, int> seg[15];
int main()
{
ll n, k;
read(n), read(k);
for (int i = 1; i <= k; i++)
{
scanf("%d %d", &seg[i].first, &seg[i].second);
}
dp[1] = sum[1] = 1;
for (int i = 2; i <= n; i++)
{
for (int j = 1; j <= k; j++)
{
int l = seg[j].first, r = seg[j].second;
dp[i] = (dp[i] + sum[max(0, i - l)] - sum[max(0, i - r - 1)] + 998244353) % 998244353;
}
sum[i] = (sum[i - 1] + dp[i]) % 998244353;
}
cout << dp[n] << endl;
}