P8846 『JROI-7』PMK 配匹串符字

简要题意

给出一正整数 \(n(1 \leq n \leq 10^5)\),求出一个由小写英文字母组成的字符串 \(S\),使得 \(|S|=n\) 且 \(\sum_{i=1}^{n}{\operatorname{Next}_i}\) 最小。(如果有多组解,输出任意一组解即可)

注:\(\operatorname{Next}\) 为 \(S\) 的失配数组。

思路

首先失配数组和最小的话当然是 \(0\),那怎么是 \(0\) 呢?考虑失配数组的定义。\(\operatorname{Next}_i\) 为 \(S[1:i]\) 中最长的前缀使其等于后缀的长度。如果 \(\operatorname{Next}_i=0\) 那么不存在前缀=后缀。怎样不存在?直接构造一个 \(\texttt{abbbbbb...}\) 即可。

时间复杂度 \(O(n)\)。

代码

#include <bits/stdc++.h>
using namespace std; signed main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
if(i==1)putchar('a');else putchar('b');
}
return 0;
}

P8847 [JRKSJ R5] 1-1 A

简要题意

给你一个由 \(1,-1\) 组成的长度为 \(n(1 \leq n \leq 10^6)\) 的序列 \(a\),你需要将其重排,使得最大子段和最小。输出重排后的序列。(如果有多组解,输出任意一组解即可)

思路

首先,直觉告诉我们,一定要 \(\texttt{1 -1 1 -1 ...}\) 这样交错输出。

如果 \(1\) 的数量不等于 \(2\) 的数量呢?我一开始的思路是从中间二分插入,但是这样子是错误的。

事实上,如果 \(-1\) 的数量大于 \(1\) 的数量,我们直接将 \(-1\) 拼到后面去,这样子可以做到最大子段和为 \(1\)。

如果 \(1\) 的数量大于 \(-1\) 的数量呢?我们同样拼到后面去,这样子可以做到最大子段和为 \(\textbf{1 的数量}-\textbf{-1 的数量}\)。

可证明这已经是最优的。

时间复杂度 \(O(n)\)。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std; int n;
int pos,neg; signed main(){
ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
cin>>n;
for(int i=1,v;i<=n;i++){
cin>>v;
if(v==1)pos++;
else neg++;
}
int init=1;
for(int i=1;i<=n&&pos&&neg;i++){
cout<<init<<' ';
if(init==1)pos--;
else neg--;
init=(-init);
}
if(pos>0){
while(pos--)cout<<1<<' ';
}
if(neg>0){
while(neg--)cout<<-1<<' ';
}
return 0;
}

P8848 [JRKSJ R5] 1-1 B

简要题意

给你一个由 \(1,-1\) 组成的长度为 \(n(1 \leq n \leq 10^4)\) 的序列 \(a\),询问有多少个将 \(a\) 重排后的序列使得该序列的最大子段和最小化。答案对 \(998244353\) 取模。

思路

首先由上题得在 \(1\) 的个数(下设为 \(p\))大于 \(-1\) 的个数)(下设为 \(e\))时,最大子段和的最小值 \(L=\sum a\),在 \(p<e\) 时 \(L=1\),在 \(p=e\) 时 \(L=0\)。

  • 当 \(p\leq e\) 时,与 \(-1\) 和 \(1\) 的位置无关,我们可以直接将 \(-1\) 固定,到里面插入 \(1\)。因此此时答案为 \(\binom{p}{e+1}\)。
  • 当 \(p>e\) 时,与位置有关,我们考虑 DP,设 \(f_{i,j}\) 为前 \(i\) 个数凑出和为 \(j\) 的方案数,则动态转移方程:
\[f_{i,j}=f_{i-1,j-1}+f_{i-1,j+1}\ \ \ \ \ f_{0,0}=1\ \ \ \ \ f_{i,0}=f_{i-1,1}
\]

推导过程 \(f_{i,j}\) 可以从从 \(f_{i-1,j-1}\) 中加上 \(1\) 得来,也可以从 \(f_{i-1,j+1}\) 中减去 \(1\) 得来。\(f_{i,0}\) 只能从 \(f_{i-1,1}\) 中减去 \(1\) 得来。

但是对于 \(1 \leq n \leq 10^4\) 时 \(f\) 空间开不下,需要进行滚动数组优化。

时间复杂度 \(O(n^2)\)(\(p>e\))或 \(O(n\log n)\)(\(p\leq e\))。

代码

#include<bits/stdc++.h>
#define int long long
using namespace std; int f[10005],fold[100005];
int fact[10005];
const int mod = 998244353;
int n,pos,neg,sum; int pow(int a,int b,int mod) {
int ans=1;
for(;b;b>>=1,a=1ll*a*a%mod) {
if(b&1) {
ans=1ll*ans*a%mod;
}
}
return ans;
} int inv(int x){
return pow(x,mod-2,mod);
} int c(int m,int n){
return (fact[n]*inv(fact[m])%mod)*inv(fact[n-m])%mod;
} signed main(){
cin>>n;
for(int i=1,v;i<=n;i++){
cin>>v;
if(v==1)pos++;
else neg++;
sum+=v;
}
if(neg>=pos){
fact[0]=fact[1]=1;
for(int i=2;i<=(n+1);i++){
fact[i]=fact[i-1]*i%mod;
}
cout<<c(pos,neg+1)<<'\n';
return 0;
}
f[0]=fold[0]=1;
for(int i=1;i<=n;i++){
f[0]=fold[1];
for(int j=1;j<=sum;j++){
f[j]=(fold[j-1]+fold[j+1])%mod;
}
memcpy(fold,f,sizeof(f));
}
cout<<f[sum]<<'\n';
return 0;
}

最新文章

  1. JS继承之借用构造函数继承和组合继承
  2. MVC5 网站开发之六 管理员 1、登录、验证和注销
  3. rsync同步
  4. 利用PHP从淘宝采集评论和成交数据
  5. 使用python递归子目录处理日志文件
  6. oracle 认证方式
  7. eclipse一直卡住,出现 “android sdk content loader 0%” 卡住的错误分析及解决方法
  8. 小结getBytes()默认编码导致的xml字符串中出现乱码
  9. EF 用CallContext上下文管理
  10. 《Genesis-3D开源游戏引擎--横版格斗游戏制作教程05:技能读表》
  11. 每天一句 linux命令
  12. Error Creating Deployment 有关Tomcat配置问题
  13. setjmp/longjmp 使用
  14. PC远程调试设备(转)
  15. VS2012下基于Glut 矩阵变换示例程序2:
  16. 2016——3——16 kmp 7题
  17. UVa 311 - Packets
  18. 自动化测试:behave
  19. JAVA之Math类常用数学运算记录
  20. mongodb shell和Node.js driver使用基础

热门文章

  1. sql面试50题------(21-30)
  2. JUC(8)Stream流式计算
  3. SpringBoot内置工具类,告别瞎写工具类了
  4. Java多线程(4):ThreadLocal
  5. IP分类与子网划分
  6. Excel中的VLOOKUP函数
  7. csp2022第一轮游记
  8. vue3 结合 element-plus 框架实现增删改查功能(不连接数据库)
  9. vue 过滤器时间格式化
  10. MIT6.828学习笔记1