D - Between Two Arrays
题目:
Time Limit: 2 sec / Memory Limit: 1024 MB
Sample Input
10
1 2 3 4 5 6 7 8 9 10
1 4 9 16 25 36 49 64 81 100
Sample Output
978222082
大意:
存在a,b两个大小为n的非减数组,consider一个非减大小为n的数组c
满足:ai ≤ ci ≤ bi for every i (1 ≤ i ≤ N)
求数组c的个数
分析
感觉本题类似 Atcode - ABC 211 - C - chokudai
只是本题要以区间的方式去思考,也是才用乘变和的思想,利用前一段来影响后一段(即后一段取决于前一段的个数),就是要找枚举前一段符合条件的个数。
AC code:
#include<iostream>
using namespace std;
const int mod = 998244353;
long long a[10010];
long long b[10010];
long long c[10010];
int main(){
int n;
cin >> n;
for(int i=1;i<=n;i++){
cin >> a[i];
}
for(int i=1;i<=n;i++){
cin >> b[i];
}
c[0]=1; //方便实现c[1]++;
for(int i=0;i<=b[n];i++){
for(int j=1;j<=n;j++){
if(i >= a[j] && i <=b[j]) c[j] = (c[j] + c[j-1])%mod;
}
}
cout << c[n];
}
Editorial 采用的是dp写法
code:
#include <iostream>
#include <vector>
#include "atcoder/modint.hpp"
using namespace std;
using mint = atcoder::modint998244353;
#define rep(i, n) for (int i = 0; i < (n); i++)
int main() {
int N;
cin >> N;
vector<int> A(N), B(N);
for (auto& x : A) cin >> x;
for (auto& x : B) cin >> x;
int MAX = 3000;
vector dp(vector(N + 1, vector(MAX + 1, mint{0})));
dp[0][0] = 1;
rep(i, N + 1) {
rep(j, MAX) dp[i][j + 1] += dp[i][j];
if (i != N) {
for (int j = A[i]; j <= B[i]; j++) dp[i + 1][j] += dp[i][j];
}
}
cout << dp[N][MAX].val() << "\n";
}