首页 > 其他分享 >abc222D 夹在两升序数组之间的升序数组个数

abc222D 夹在两升序数组之间的升序数组个数

时间:2024-03-12 21:00:15浏览次数:19  
标签:pre int rep 数组 升序 abc222D sum dp

给定长度为n的两升序数组A[i]和B[i],其中A[i]<=A[i+1],B[i]<=B[i+1],并且0<=A[i]<=B[i]<=3000,找长度为n的数组C[i],满足A[i]<=C[i]<=B[i]。求满足该条件的C的个数,结果对998244353取余。
1<=n<=3000

设dp[i][j]表示前i个数以j结尾的方案数,那么$ dp[i][j]=\sum_{k=0}^{j} dp[i-1][k] $,这样递推时间复杂度是O(n^3),会TLE。观察发现这个可以用前缀和优化到O(n^2),另外可以用滚动数组优化空间到O(n)

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,a,b) for(int i=a; i<=b; i++)
#define per(i,a,b) for(int i=b; i>=a; i--)

template<int MOD>
struct MInt {
    int x;
    int norm(int u) const {u%=MOD; if(u<0) u+=MOD; return u;}
    MInt(int v=0):x(norm(v)) {}
    int val() const {return x;}
    MInt operator-() const {return MInt(norm(MOD-x));}
    MInt inv() const {assert(x!=0); return power(MOD-2);}
    MInt &operator*=(const MInt &o) {x=norm(x*o.x); return *this;}
    MInt &operator+=(const MInt &o) {x=norm(x+o.x); return *this;}
    MInt &operator-=(const MInt &o) {x=norm(x-o.x); return *this;}
    MInt &operator/=(const MInt &o) {*this *= o.inv(); return *this;}
    friend MInt operator*(const MInt &a, const MInt &b) {MInt ans=a; ans*=b; return ans;}
    friend MInt operator+(const MInt &a, const MInt &b) {MInt ans=a; ans+=b; return ans;}
    friend MInt operator-(const MInt &a, const MInt &b) {MInt ans=a; ans-=b; return ans;}
    friend MInt operator/(const MInt &a, const MInt &b) {MInt ans=a; ans/=b; return ans;}
    friend std::istream &operator>>(std::istream &is, MInt &a) {int u; is>>u; a=MInt(u); return is;}
    friend std::ostream &operator<<(std::ostream &os, const MInt &a) {os<<a.val(); return os;}
    MInt power(int b) const {int r=1, t=x; while(b){if(b&1) r=r*t%MOD; t=t*t%MOD; b/=2;} return MInt(r);}
};
using mint = MInt<998244353>;

const int N = 3000;
int n, a[N+1], b[N+1];
mint dp[N+1], pre[N+1];
mint sum(int l, int r) {
    return l ? pre[r] - pre[l-1] : pre[r];
}
void solve() {
    cin >> n;
    rep(i,1,n) cin >> a[i];
    rep(i,1,n) cin >> b[i];
    dp[0] = 1;
    partial_sum(dp, dp+1+N, pre);
    rep(i,1,n) {
        rep(j,0,N) dp[j] = 0;
        rep(j,a[i],b[i]) {
            dp[j] = sum(a[i-1], j);
        }
        partial_sum(dp, dp+1+N, pre);
    }
    cout << pre[N] << "\n";
}

signed main() {
    cin.tie(0)->sync_with_stdio(0);
    int t = 1;
    while (t--) solve();
    return 0;
}

标签:pre,int,rep,数组,升序,abc222D,sum,dp
From: https://www.cnblogs.com/chenfy27/p/18069270

相关文章

  • 02-数组、排序、查找
    数组数组是一种引用数据类型,所以数组对象实际上存储在堆内存当中数组实际上是一种容器,可以容纳多个元素数组中存储的是基本数据类型的数据,或者是引用数据类型的引用(不能直接存储Java对象)长度不可变,起始位置是0,最后一个下标是length-1所有的数组对象都有length属性Java中......
  • 树状数组
    树状数组基础基础部分点击查看代码......
  • 【IC验证】数组
    一、非组合型数组1.声明logic[31:0]array[1024];或者logic[31:0]array[1023:0];或者logicarray[31:0][1023:0];理解成一维数组就表示array数组中有1024个数据,每个数据32bit。也可以理解为二维数组。int[1:0][2:0]a1[3:0][4:0]这是一个4×5×2×3维(高维-......
  • 一维数组和二维数组传参是不同的:
    数组传参,传递的实质是首元素的地址。(一)一维数组例:写一个函数对将一个整型数组的内容,全部置为-1,再写一个函数打印数组的内容.#include<stdio.h>voidreset(intarr[],intx)//形参和实参名可以相同也可以不相同{ inti=0; for(size_ti=0;i<x;i++) { arr[i......
  • 蓝桥杯2019年第十届省赛真题-修改数组
    查重类题目,想到用标记数组记录是否出现过但是最坏情况下可能会从头找到小尾巴,时间复杂度O(n2),数据范围106显然超时再细看下题目,我们重复进行了寻找是否出现过,干脆把每个元素出现过的次数k记录下来,直接跳到后k个位置,实现O(n)#include<stdio.h>#include<string.h>#inclu......
  • 【算法】【线性表】【数组】在排序数组中查找元素的第一个和最后一个位置
    1 题目给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值 target,返回 [-1,-1]。你必须设计并实现时间复杂度为 O(logn) 的算法解决此问题。示例1:输入:nums=[5,7,7,8,8,......
  • java8中,Arrays.sort()默认是升序的,对于基本数据类型,使其降序怎么实现
    对于引用数据类型,自定义比较器对象,实现Comparator接口/Comparable接口对于基本数据类型,自定义比较器对象,将基本数据类型转换成对应的包装类型即可但是这样写是错误的,importjava.util.Arrays;importjava.util.Comparator;publicclassSortExample{publicstatic......
  • 【算法】【线性表】【链表】合并 K 个升序链表
    1 题目给你一个链表数组,每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中,返回合并后的链表。示例1:输入:lists=[[1,4,5],[1,3,4],[2,6]]输出:[1,1,2,3,4,4,5,6]解释:链表数组如下:[1->4->5,1->3->4,2->6]将它们合并到一个有序链表中得到。1-......
  • (C++)树状数组和线段树的VSCode Snippet
    学都学了,肯定要往snippet里塞好东西嘛{ //Placeyoursnippetsforcpphere.Eachsnippetisdefinedunderasnippetnameandhasaprefix,bodyand //description.Theprefixiswhatisusedtotriggerthesnippetandthebodywillbeexpandedandinserted.......
  • labuladong_二维数组遍历
    1.二维数组进行旋转,图像顺时针旋转90度1.1我们可以先将 nxn 矩阵 matrix 按照左上到右下的对角线进行镜像对称:然后再对矩阵的每一行进行反转:发现结果就是 matrix 顺时针旋转90度的结果://将二维矩阵原地顺时针旋转90度 //逆时针旋转90度   ......