首页 > 其他分享 >洛谷P8848 [JRKSJ R5] 1-1 B

洛谷P8848 [JRKSJ R5] 1-1 B

时间:2022-12-09 14:12:28浏览次数:56  
标签:P8848 洛谷 int 下界 JRKSJ 序列 mul include mod

给定一个由 \(1\) 和 \(-1\) 序列 \(a\),询问有多少个将 \(a\) 重排后的序列使得该序列的最大子段和最小化,称两个序列不同,当且仅当这两个序列有任意一个位置上的数不同

考虑最大的最大字段和的一个区间 \([l,r]\),\(a_{l-1}\) 和 \(a_{r+1}\) 一定是 \(-1\),令 \(1\) 的数量为 \(A\),\(-1\) 的数量为 \(B\),若 \(A>B\),那么全局和 \(A-B\) 一定是最大字段和的下界,否则下界为 \(1\)

考虑如何取到下界,若 \(A\leq B\),我们要保证每个 \(1\) 的相邻位置都为 \(-1\),经典插板法,方案数即为 \(\binom{B + 1}{A}\)

若 \(A>B\),该问题就可以转化成走格子,每次可以从 \((i, j)\) 走到 \((i + 1, j + 1)\) 或 \((i + 1, j - 1)\),且不能走到 \(y = -1\) 以及 \(y = A - B + 1\) 两条线,最后要求的就是走到 \((n, A - B)\) 的方案数,简单DP即可,复杂度 \(O(n^2)\)

参考 P3266 [JLOI2015]骗我呢 可以做到 \(O(n)\) 的复杂度

这里给出 \(O(n^2)\) 的代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>

#define file(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout);
#define dbg(x) cerr<<"In Line"<<__LINE__<<" the "<<#x<<" = "<<x<<'\n';
#define abs(x) ((x) < 0 ? -(x) : (x))

using namespace std;

const int N = 2e6 + 10, mod = 998244353;

inline int read() {
	bool sym = 0; int res = 0; char ch = getchar();
	while (!isdigit(ch)) sym |= (ch == '-'), ch = getchar();
	while (isdigit(ch)) res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar();
	return sym ? -res : res;
}

int n, m, k, cnt1, cnt2, mul[N], f[2][10010];

int qpow(int a, int x) {
	int res = 1;
	while (x) {if (x & 1) res = 1ll * res * a % mod; a = 1ll * a * a % mod; x >>= 1;}
	return res;
}

int C(int n, int m) {
	return 1ll * mul[n] * qpow(mul[m], mod - 2) % mod * qpow(mul[n - m], mod - 2) % mod;
}

int main() {
	n = read(); mul[0] = 1;
	for (int i = 1; i <= 100000; i++) mul[i] = 1ll * mul[i - 1] * i % mod;
	for (int i = 1; i <= n; i++) if (read() == 1) cnt1++; else cnt2++;
	if ((cnt1 == 1 || cnt2 == 1) && n == 1) {printf("2"); return 0;}
	if (cnt1 == 1 && cnt2 == 1) {printf("2"); return 0;}
	if (cnt1 == 1 && cnt2 == 2) {printf("3"); return 0;}
	if (cnt1 == cnt2) {printf("%d", n / 2 + 1); return 0;}
	if (cnt1 < cnt2) {printf("%d", C(cnt2 + 1, cnt1)); return 0;}
	f[0][0] = 1; m = cnt1 - cnt2;
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j <= min(i, m); j++) {
			f[i & 1][j] = 0;
			if (j - 1 >= 0) f[i & 1][j] = f[i & 1 ^ 1][j - 1];
			if (j + 1 <= m + 1) f[i & 1][j] = 1ll * (f[i & 1][j] + f[i & 1 ^ 1][j + 1]) % mod;
		}
		// for (int j = 0; j <= m; j++) printf("%d ", f[i & 1][j]); printf("\n");
	}
	printf("%d", f[n & 1][cnt1 - cnt2]);
	return 0;
}

标签:P8848,洛谷,int,下界,JRKSJ,序列,mul,include,mod
From: https://www.cnblogs.com/zrzring/p/LGP8848.html

相关文章

  • 洛谷月赛简单题目选做
    简单题目指黄+~蓝P5888传球游戏Easy考虑朴素dp,设\(dp[i][j]\),表示第\(j\)轮球在\(i\)手中的方案数,时间复杂度\(O(nm)\)。观察到如果两个人均不是\(1\)号......
  • 洛谷 P1957 口算练习题
        实现代码(原创):#include<stdio.h>#include<string.h>#include<stdlib.h>char*itoa(intvalue,char*str,intradix){staticchardig[]=......
  • 洛谷P2504聪明的猴子
    思路:最小生成树1#include<cstdio>2#include<cstdlib>3#include<iostream>4#include<cstring>5#include<cmath>6#include<algorithm>7#include<vecto......
  • 洛谷P1111修复公路
    思路:并查集1#include<cstdio>2#include<iostream>3#include<algorithm>4#include<math.h>5#include<vector>6#include<set>7usingnamespacestd;......
  • 【洛谷P8866】喵了个喵
    题目题目链接:https://www.luogu.com.cn/problem/P8866小E喜欢上了一款叫做《喵了个喵》的游戏。这个游戏有一个牌堆和\(n\)个可以从栈底删除元素的栈,任务是要通过游......
  • 洛谷 P1891 疯狂 LCM
    \(\text{lcm}\)不好处理,转化为\(\gcd\):\[n\sum_{i=1}^n\frac{i}{\gcd(i,n)}\]\(\gcd\)相关题目的套路——枚举因数:\[n\sum_{d|n}\sum_{i=1}^n\fracid[......
  • 洛谷 P4552 [Poetize6] IncDec Sequence(差分)
    题目分析直接贴一个洛谷上的题解,真的秀,讲的又清楚又好要使得序列的数全部相等,其实就是让他们之间的差全为0,也就是差分序列的除了第一项每一项都是0,为什么除了第一项呢,因......
  • 洛谷 P1387 最大正方形(前缀和,二分)
    题目分析当一个边长为x的正方形不包含0时,这个正方形内的二维前缀和为x*x,题目想求满足条件的最大的正方形的边长假如最大的正方形的边长为ans,那么凡是边长大于ans的正方形......
  • 洛谷 P1205 [USACO1.2] 方块转换 Transformations
    [USACO1.2]方块转换Transformations题目描述一块\(n\timesn\)正方形的黑白瓦片的图案要被转换成新的正方形图案。写一个程序来找出将原始图案按照以下列转换方法转......
  • 洛谷-P5541 Sleepy Cow Herding S
    SleepyCowHerdingSSleepyCowSorting的升级版,从\(3\)头牛变成\(n\)的情况分类讨论+双指针先把答案本就连续的特判丢掉最大值最大值就尽量把每个空位......