P1371 NOI元丹
题目描述
小A打算开始炼 NOI\texttt{NOI}NOI 元丹(什么鬼),据说吃了可以提高 NOI\texttt{NOI}NOI 时的成绩。
是这么练的。元丹有三种元核,N、O、I。现有很多个这样原核,按顺序排成一行。炼元丹时,从左往右分别挑出 N、O、I 三个原核吞下。
现在他关心,有几种服用方式……且慢!
他觉得服用方式太少,以至于不能成仙。所以他可以通过某个途径,得到 N、O、I 的三种原核中的任意一个,至于哪一种由他决定。然后他将获得这个原核的插入到这一排原核中的任意位置(包括最前最后)。
现在你要知道,新的元核序列中能有多少种 N、O、I 的取出方式。子串的字母并不要求连续。
输入格式
第一行,一个整数 NNN,表示字符串的长度。
第二行,一行字符串,里面只有只有 N、O、I 三种字母。
输出格式
表示出最多可以提炼出来的 NOI\texttt{NOI}NOI 元丹的方案种数。
输入输出样例 #1
输入 #1
5
NOIOI
输出 #1
6
说明/提示
样例解释:
他可以获取一个 N 元核,加到最前面。
NNOIOI | NNOIOI | NNOIOI | NNOIOI | NNOIOI | NNOIOI
~ ~~ | ~ ~ ~ | ~ ~~ | ~~~ | ~~ ~ | ~ ~~
对于 30%30\%30% 的数据 N≤200N \le 200N≤200。
对于 50%50\%50% 的数据 N≤2000N \le 2000N≤2000。
对于 100%100\%100% 的数据 3≤N≤1053 \le N \le 10 ^ 53≤N≤105。
C++实现
#include
#include
#include
#include
#define maxn 100000+10
using namespace std;
string s;
long long N[maxn],O[maxn],I[maxn];//pre
long long n,sum[maxn],MAXN,MAXO,MAXI,MAXS;
int main()
{
cin>>n;
char temp=getchar();
s.push_back(‘0’);
for(int i=1;i<=n;i++)
{
temp=getchar();
if(temp==‘N’)
N[i]++;
if(temp==‘O’)
O[i]++;
if(temp==‘I’)
I[i]++;
N[i]+=N[i-1];
O[i]+=O[i-1];
I[i]+=I[i-1];
s.push_back(temp);
}
for(int i=1;i<=n;i++)
{
if(s[i]==‘O’)
{
sum[i]+=N[i-1](I[n]-I[i]);
MAXO=max(MAXO,N[i-1](I[n]-I[i]));
MAXN+=I[n]-I[i];
MAXI+=N[i-1];
}
sum[i]+=sum[i-1];
}
MAXS=max(MAXO,max(MAXN,MAXI));
cout<<sum[n]+MAXS;
}

后续
接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容
用C++实现信奥 P1371 NOI元丹&spm=1001.2101.3001.5002&articleId=146411362&d=1&t=3&u=455b736fdbfc4d61807cb8e7e7e32d32)

被折叠的 条评论
为什么被折叠?



