题目链接
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
对于大部分编程语言来说,编写一个能够输出 “Hello World!” 的程序往往是最基本、最简单的。
因此,这个程序常常作为一个初学者接触一门新的编程语言所写的第一个程序,也经常用来测试开发、编译环境是否能够正常工作。
陈末也为大家准备了这么一道题,现在你就可以通过写一个输出 “Hello World!” 的程序来通过这道题啦~
Froshine : “或许,梦开始的地方也是最后无人问津的地方吧~”
输入描述:
无
输出描述:
Hello World!
示例1
输入:
输出:
Hello World!
解题思路
无
代码
1.C++解法
#include
using namespace std;
int main() {
cout<<"Hello World!";
return 0;
}
2.PHP解法
Hello World! //PHP是最好的语言()
题目链接
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
众所周知,陈末的数学很差。
陈末连简单函数解析都处理不了,所以他想请你帮他处理。
定义
f ( x ) = { 1 x = 0 2 x = 1 3 x = 2 4 x = 3 f ( x − 1 ) + f ( x − 3 ) x > 3 f(x) = \left\{ \begin{array}{lr} 1 && x = 0\\ 2 && x = 1\\ 3 && x = 2\\ 4 && x = 3\\ f(x-1) + f(x-3) && x > 3\\ \end{array} \right. f(x)=⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧1234f(x−1)+f(x−3)x=0x=1x=2x=3x>3
对于给定的 x ,输出对应 f(x) 的值。
由于最后答案可能很大,请输出将答案对 109 + 7 取模的结果。
输入描述:
一行,一个数 x (1 ≤ x ≤ 105)
输出描述:
输出对应 f(x) 的值
示例1
输入:
0
输出:
1
示例2
输入:
2
输出:
3
示例3
输入:
6666
输出:
193444274
解题思路
刚上手用的递归,结果爆T了,因为递归栈溢出
链接:递归太深会导致栈溢出
换成递推过了
代码
1.递归解法(TLE错误解法)
#include
using namespace std;
int x;
const int mod = 1e9+7;
int fun(int x){
if(x==0) return 1;
else if(x==1) return 2;
else if(x==2) return 3;
else if(x==3) return 4;
else return(fun(x-1)+fun(x-3))%mod;
}
int main(){
cin>>x;
cout<<fun(x);
return 0;
}
2.递推解法
#include
using namespace std;
#define ll long long
const int maxn = 1e5 + 10;
const int mod = 1e9 + 7;
ll f[maxn];
int main(){
f[0] = 1, f[1] = 2, f[2] = 3, f[3] = 4;
for(int i = 4; i <= 1e5; ++i){
f[i] = (f[i - 1] + f[i - 3]) % mod; //每次取mod防止f[i]爆数据范围
}
ll x;
cin >> x;
cout << f[x];
return 0;
}
题目链接
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
因为陈末英雄联盟玩的太菜,青钢影就对陈末使用了大招 “海克斯最后通牒” ,将陈末困了起来,不让他继续祸害其他队友。
陈末向青钢影求饶,青钢影就给了陈末一个不等式 2n > n2 。
并要求他回答出当 n 为一些值的时候,等式是否成立。
只有陈末能正确回答,青钢影才会放他出来。
陈末数学太烂了,所以他请到了聪明的你来帮帮他。
输入描述:
第一行一个整数 n(1 ≤ n ≤ 109) ,代表 n 的值。
输出描述:
如果等式成立输出 “YES”(不包括双引号) ,否则输出 “NO”(不包括双引号)。
示例1
输入:
2
输出:
NO
说明:
此时两边相等
示例2
输入:
5
输出:
YES
解题思路
直接判断,或者输出几个n找规律
代码
#include
using namespace std;
int n;
int main(){
cin>>n;
if(pow(2,n)>n*n) cout<<"YES";
else cout<<"NO";
return 0;
}
#include
using namespace std;
int main(){
int n;
cin >> n;
if(n == 1 || n >= 5)puts("YES");
else puts("NO");
return 0;
}
题目链接
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
AK是每个acmer在每场比赛中的最大追求。
(AK:指在一次比赛中把全部题目都写出来了)
周波廷学长正在整理自己的训练成绩。
我们将训练赛的名字的简化成为一个个的字符串。
给定 n 个字符串。如果一个字符串的结尾是 “AK” ,那么这次训练的成绩就是AK。请你输出哪次比赛会AK。
如果有多个次AK,输出最靠前的一个。
数据保证一定有解。
输入描述:
第一行一个数整数 n(1 ≤ n ≤ 1 × 102) ,表示字符串的数量。
接下来 n 行,一行一个字符串 ,保证每个字符串大小不超过100。
输出描述:
输出一个字符串(比赛的名字),表示这次比赛AK了且最靠前(不包含"AK")。
示例1
输入:
3
acmer
ICPCAK
CCPCAK
输出:
ICPC
说明:
周波廷学长在ICPC与CCPC都AK了,但是ICPC排名更靠前
示例2
输入:
2
atcoder
codeforcesAK
输出:
codeforces
说明:
周波廷学长只在codeforcesAK了
解题思路
用字符串数组存入,遍历字符串,如果最后两个字符是“AK”就输出该字符串前length-2位,并提前结束
代码
#include
using namespace std;
int n;
string s[110];
int main(){
cin>>n;
for(int i = 0;i<n;i++) cin>>s[i];
for(int i = 0;i<n;i++){
int len = s[i].length();
if(s[i][len-2]=='A'&&s[i][len-1]=='K') {
for(int j = 0;j<len-2;j++) cout<<s[i][j];
return 0;
}
}
return 0;
}
#include
using namespace std;
const int maxn = 1e5 + 10;
string a[maxn];
int main(){
int n ;
cin >> n ;
for (int i = 1; i <= n; ++i) cin >> a[i];
for (int i = 1; i <= n; ++i){
int len = a[i].size() ;
if (len >= 2){
string tp = a[i].substr(len - 2, 2) ; //截取str的后两位字符
if (tp == "AK"){
for (int j = 0; j < len - 2; ++j)
cout << a[i][j];
cout << endl;
return 0;
}
}
}
return 0;
}
题目链接
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
众所周知,陈末是个英雄联盟菜鸟,又菜又爱玩。
陈末特别喜欢用派克来秀他下饭的操作,每次都能把自己秀死。
涌泉之恨是派克的大招,能在一定情况下,直接斩杀敌人。
此时陈末操作的派克在一个 N行 ,M 列 的二维空间中。
我们将问题简化,让派克的大招能直接斩杀一个十字形的区域内的敌人(这很码头菩萨),并且能触发连斩机制。
例如: 当派克斩杀的敌人坐标在 (i, j) ,那么(i, j) , (i+1, j) , (i, j+1) , (i-1, j) , (i, j-1)这些位置上的敌人都会被斩杀,并且除位置在 (i, j) 外的敌人 如果被斩杀就会触发连斩机制,将这个位置变成新的 (i, j),并斩杀十字区域的敌人,以此类推。
陈末可以操纵派克选择二维空间中的任何一个敌人使用涌泉之恨。
陈末想借用科技的力量操作一次,请你来帮他计算出一次最多能斩杀出多少敌人。
输入描述:
第一行两个数 n(1 ≤ n ≤ 102) ,m(1 ≤ n ≤ 102) ,分别二维空间的行数和列数。
下面有 n 行 ,每行 m 个字符,代表二维空间的敌人分布情况。
*代表这个位置有一个敌人, # 代表这个位置没有敌人。
输出描述:
输出一次最多能斩杀出多少敌人。
示例1
输入:
4 4
# * # #
* * * #
# # * #
# * # #
输出:
5
说明:
选择坐标(1, 2),(2, 1),(2, 2),(2, 3),(3, 3)中的任意一个敌人斩杀将触发连斩机制,进而斩杀5个敌人。
示例2
输入:
3 3
# * #
* * #
* # *
输出:
4
说明:
选择坐标(1, 2),(2, 1),(2, 2),(3,1)中的任意一个敌人斩杀将触发连斩机制,进而斩杀4个敌人。
解题思路
选中一个存在敌人的点斩杀,如果该点的上下左右也有敌人那么也会被斩杀,直到每个点的上下左右都没有敌人时停止,求一次最多斩杀敌人数量。
也就是可以理解为求最大连通块的数量
代码
#include
using namespace std;
const int N = 1e2 + 3, M = 1e2 + 3;
int fx[] = {0, 0, -1, 1};
int fy[] = {-1, 1, 0, 0};
char a[N][M];
int vis[N][M];
int sum, ans;
int n, m;
void dfs(int x, int y){
vis[x][y] = 1; //1为搜索过
sum++; //sum 当前连通块数量
for(int i = 0; i < 4; ++i){ //搜索十字方向的点
int xx = x + fx[i], yy = y + fy[i];
if(xx < 1 || xx > n || yy < 1 || yy > m)continue; //越界
if(a[xx][yy] == '#')continue; //没有敌人
if(vis[xx][yy])continue; //已经搜过
dfs(xx, yy);
}
}
int main(){
scanf("%d %d\n", &n, &m);
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= m; ++j){
scanf("%c", &a[i][j]);
}
getchar();
}
int ans = 0;
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= m; ++j){
if(a[i][j] == '*' && !vis[i][j]){ //有敌人&&是新的连通块
sum = 0;
dfs(i, j);
ans = max(ans, sum);
}
}
}
cout << ans << endl;
return 0;
}
题目链接
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
一天,贺志飞学长收到了一封信,信里有 n 个序列。
每个序列长度为 S 。
每个序列中有 W1 ,W2 ,W3……Ws。
来信的人让贺志飞学长对这些序列中完全相同的序列进行去重操作(删除其他相同的,只保留一个)。
如果去重能正确完成,贺志飞学长将得到一笔丰厚的报酬。
为了得到报酬,贺志飞学长请到了聪明的你来帮忙。
输入描述:
第一行一个整数 n(1 ≤ n ≤ 2 ×105) ,代表有N个数组。
下面 n 行,每行包含一个整数 S,表示数组的元素个数,以及 S 个整数W1 ,W2 ,W3……Ws ,Wi(1 ≤ Wi ≤ 109),代表数组的元素。
保证 n 个数组的元素个数总和不超过 2 ×105。
输出描述:
要求输出去重后的数组有多少个。
示例1
输入:
4
2 1 3
2 1 1
2 3 1
2 1 3
输出:
3
说明:
第1个数组与第4个数组完全相同,所以去重后只有3个数组了。
示例2
输入:
1
1 2
输出:
1
解题思路
题目要求是数组去重,利用set集合中每个元素的值唯一的特点即可
代码
#include
using namespace std;
int main(){
int T;
scanf("%d", &T);
set<vector<int>> s; //数组set
while(T--){ //T个数组
int n;
scanf("%d", &n);
vector<int> tmp;
for(int i = 1; i <= n; ++i){
int x;
scanf("%d", &x);
tmp.push_back(x);
}
s.insert(tmp); //数组插入set
}
cout << s.size() << endl;
return 0;
}
题目链接
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
王梦涵学长,有着 n 个迷弟。每个迷弟有着自己的力量值。
为了让迷弟们和自己一样强大,王梦涵学长学习了一种增幅魔法,每次使用魔法可以让一位迷弟的力量值加 1 。
例如,王梦涵学长有3个迷弟,力量分别为[1,2,3],王梦涵学长使用一次魔法使得1号迷弟的力量加1,变成[2,2,3]。
但是魔法不能无限使用,王梦涵学长最多只能使用 k 次魔法。
王梦涵学长十分关照力量值比较低的迷弟。所以他想在使用不超过 k 次魔法后,使得全部迷弟中力量值最低的迷弟,力量值最大。
请你帮帮王梦涵学长计算在上方的原则下,力量值最低的迷弟的力量值。
输入描述:
第一行两个数整数 n(1 ≤ n ≤ 2 ×105) ,k(1 ≤ k ≤ 2 ×105),表示迷弟的人数以及使用魔法的最大次数。
接下来一行 n 个数 ai(1 ≤ ai ≤ 2 ×105) ,表示第i个迷弟的力量值。
输出描述:
输出一个数,表示在使用不超过 k 次魔法后,迷弟中,力量值最低的迷弟的最大力量值。
示例1
输入:
5 3
1 1 3 3 4
输出:
2
说明:
一种方法为从[1,1,3,3,4]加到[3,2,3,3,4],此时最小力量值为2。
解题思路
最大化最小值问题,用二分搜索求结果。
先假定一个答案x,再不断缩小答案范围,最终得到解。
因为x是最大的最小值,所以x-1也满足条件,但不是最大的,x+1不满足条件,所以单调性
代码
#include
#define ll long long
using namespace std;
const int maxn = 2e5 + 10;
int a[maxn];
int n, k;
bool judge(int x){
ll sum = 0;
for(int i = 1; i <= n; ++i){
if(a[i] < x)sum += x - a[i];
//if(sum>k) return false;
}
return sum <= k;
}
int main(){
scanf("%d %d", &n, &k);
for(int i = 1; i <= n; ++i){
scanf("%d", &a[i]);
}
int L = 1, R = 1e6;
int ans;
while(L <= R){
int mid = L + R >> 1;
if(judge(mid))L = mid + 1, ans = mid;
else R = mid - 1;
}
cout << ans << endl;
return 0;
}
题目链接
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
某一天李华来到了巧星球,这个星球碰巧和地球很像,日期和地球很相似,除了1,7,10月天数为40天外其他完全相同,碰巧巧星球也有闰年的概念,碰巧李华接到了一个任务,这个任务是计算两个日期之间相差的天数,碰巧你也来到了巧星球,李华想找你帮忙,这次不需要写信,只需要计算即可QWQ。
计算巧星球两个日期之间相差天数(1,7,10天数为40,其他碰巧与地球相同),答案可能很大,但保证最终结果不超过int范围
输入描述:
输入两个日期,年/月/日,两日期用空格隔开
年份(1 ≤ 年份 ≤ 109)
保证输入日期合法
输出描述:
输出一个整数
示例1
输入:
2022/1/18 2022/2/19
输出:
41
示例2
输入:
1949/10/1 2022/1/25
输出:
28367
解题思路
计算两个日期相差天数,可以找一个共同的初始日期,分别求距离再相减。
比如以0年0月0日作为初始日期。
还有个坑,就是题目没有说明起始日期和终点日期哪个更大,所以相减完还要求个绝对值。
代码
#include
using namespace std;
#define ll long long
int mon[13] = {0,40,28,31,30,31,30,40,31,30,40,30,31}; //加总 = 392
bool isrun(ll y){
return (y%4==0&&y%100!=0||y%400==0);
}
ll counts(ll y,int m,int d){
ll sum = 0;
if(isrun(y)&&m<=2) sum--; //当年是闰年 所以算了一次,如果没到3月 就多算了一次闰月,减掉
for(int i = 1;i<m;++i) sum+=mon[i];
return 1ll*392*(y-1)+y/4-y/100+y/400+sum+d; //整年日期+闰年个数+整月日期+日
}
int main(){
ll y1,y2;
int m1,m2,d1,d2;
scanf("%lld/%d/%d %lld/%d/%d",&y1,&m1,&d1,&y2,&m2,&d2);
ll sum1=counts(y1,m1,d1),sum2=counts(y2,m2,d2);
printf("%lld",abs(sum1-sum2));
}
题目链接
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
在电影中,陈末与幺鸡约定了要在稻城再见。
但是,陈末在快抵达稻城的时候,被一群可恶的神秘人抓走了,神秘人把陈末关在了一个没有出口的二维迷宫里。
上帝见陈末如此可怜,就给了陈末一张迷宫的地图,并告诉给陈末,只要陈末能到达迷宫的边界,上帝就会花1单位时间帮他逃出迷宫。
迷宫内有毒气,毒气在每个单位时间会向四周扩散(即向四个方向扩散一个单位),毒气无法扩散到墙上。
例如,毒气此时在(x , y),那么毒气会花1个单位时间 扩散到(x,y+1),(x+1,y),(x-1,y),(x,y-1),并在新的位置再次扩散,前提为目标点不是墙,且不在迷宫范围之外。
陈末在每个单位时间只能向一个方向前进一个单位,陈末翻不了这里的墙。
例如,陈末此时在(x,y),那么陈末可以花费1个单位时间走到 (x,y+1),(x+1,y),(x-1,y),(x,y-1)中的任意一个,前提为目标点不是墙,且不在迷宫范围之外。
请问,陈末至少要花多少时间才能逃出迷宫,如果陈末始终无法逃出迷宫请输出 “NO” (不包含双引号)
输入描述:
第一行两个整数n(1≤n≤103),m(1≤m≤103),分别表示二维迷宫的行数和列数。
下面有 n 行 ,每行 m 个字符,代表二维迷宫的地图。
*代表这个位置有毒气
#代表这个位置有墙
.代表这个位置是空地
C代表陈末在这个位置
保证地图只有以上4种字符,并且C保证只出现1次。
注意:不保证毒气只有一个位置具有。
输出描述:
陈末至少要花多少时间才能逃出迷宫,如果陈末始终无法逃出迷宫请输出 “NO” (不包含双引号)
示例1
输入:
3 3
*##
*C.
###
输出:
2
说明:
陈末可以花费1个单位时间从(2,2)到达(2,3),然后上帝就会花1个单位时间救他。
示例2
输入:
4 4
####
#C*#
#*…
###.
输出:
NO
说明:
很不幸,无论陈末走哪里,他都会被毒死。
解题思路
如果陈末到达x点的最短时间比毒气到达x点的最短时间长或者相等,那么就跑不掉。
因为毒气有多个起点
所以要先bfs求每个毒气到达每个点的最短距离,
再求陈末到达每个点的最短距离,作比较。
如果在边界,不是墙并且跑得掉,花费时间就是到达边界时间+1
代码
#include
using namespace std;
const int N = 1e3+10;
const int M = 1e3+10;
int n,m;
char arr[N][M]; //存图
int cx,cy; //陈末起点
int duS[N][M],cmS[N][M]; //duS毒气到达点的时间,cmS陈末到达点的时间
int dx[] = {-1,0,1,0},dy[] = {0,1,0,-1};
typedef struct p_node{
int x,y;
}P;
queue<P> du,cm;
int main(){
cin>>n>>m;
for(int i = 1;i<=n;++i){
for(int j = 1;j<=m;++j){
cin>>arr[i][j];
duS[i][j] = cmS[i][j] = 1e9;
if(arr[i][j]=='C') cx=i,cy=j;
if(arr[i][j]=='*') du.push({i,j}),duS[i][j] = 0;
}
getchar();
}
//毒气到达时间
while(!du.empty()){
P u = du.front();
du.pop();
for(int i = 0;i<4;++i){
int xx = u.x+dx[i],yy = u.y+dy[i];
if(xx<1||xx>n||yy<1||yy>m) continue;
if(arr[xx][yy]=='#') continue;
if(duS[xx][yy]<=duS[u.x][u.y]+1) continue;
duS[xx][yy] = min(duS[xx][yy], duS[u.x][u.y]+1);
du.push({xx,yy});
}
}
//陈末到达时间
int ans = -1;
cm.push({cx,cy});
cmS[cx][cy]=0;
while(!cm.empty()){
P u = cm.front();
cm.pop();
if(u.x==1||u.y==1||u.x==n||u.y==m){
if(cmS[u.x][u.y]+1<=duS[u.x][u.y]){ //最先到达边界的点一定是时间最短的
ans = cmS[u.x][u.y]+1;
break;
}
}
for(int i = 0;i<4;++i){
int xx = u.x+dx[i],yy = u.y+dy[i];
if(xx<1||xx>n||yy<1||yy>m) continue;
if(cmS[xx][yy]<=cmS[u.x][u.y]+1) continue;
if(arr[xx][yy]=='.'&&cmS[xx][yy]>=cmS[u.x][u.y]+1){
cmS[xx][yy] = cmS[u.x][u.y]+1;
cm.push({xx,yy});
}
}
}
if(ans==-1) cout<<"NO"<<endl;
else cout<<ans<<endl;
return 0;
}
题目链接
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
一天,陈梓豪学长去注册账号。
陈梓豪学长发现网站的密码必须符合下面三个条件
密码中应该至少包括大写英文字母、小写英文字母、数字、特殊符号这四类字符中的三种。
密码的长度不少于L个字符,并且不多于R个字符。
密码是仅包含大小写英文字母、数字、特殊符号的字符串。
特殊字符,是指非大小写字母、数字以及空格回车等不可见字符的可见字符,包括但不限于"!@#^*()_+"。
现在,陈末给了陈梓豪学长一个长度大小为N的字符串S,陈梓豪学长想知道S串中有多少个子串是一个符合条件的密码。
请你帮助陈梓豪学长统计符合条件的密码数目。
子串是指字符串中某一段连续的区间,例如对于字符串"aqwerdf"来说,“aqw”,"qwe"都是它的子串,而"aqr"不是它的子串。
输入描述:
第一行输入三个正整数 N,L,R (1 ≤ N ≤105), (1 ≤ L ≤ R ≤ N),表示字符串的长度,以及合法字符的长度限制 。
第二行输入一个长度为N的字符串S。
保证字符串只包含大小写英文字母、数字、特殊符号。
输出描述:
一个整数,表示有多少个子串是一个合法的密码。
示例1
输入:
6 2 6
abcD2!
输出:
7
说明:
abcD2
bcD2
cD2
D2!
abcD2!
bcD2!
cD2!
解题思路
给一个字符串,求该字符串中符合题目要求的子串。
可以看出这是一道滑动窗口问题,我们可以用双指针来解决。
P函数处理字符的种类,flag[0]存当前子串中不重复的字符种类,flag[1]-flag[4]存当前子串中每种字符的数量
代码
#include
using namespace std;
const int N = 1e5+10;
char s[N];
int flag[5];
int cnt;
int P(int x){
if(x>='A'&&x<='Z') return 1;
if(x>='a'&&x<='z') return 2;
if(x>='0'&&x<='9') return 3;
return 4;
}
int main(){
int n,L,R;
cin>>n>>L>>R;
scanf("%s",s+1);
int l = 1,r = 0;
while(l<=n){
while(r-l+1<=R&&r<n){
int p = P(s[++r]);
if(flag[p]==0) flag[0]++;
flag[p]++;
if(flag[0]>=3&&r-l+1>=L){
cnt+=min(n-r+1,R-(r-l+1)+1);
break;
}
}
int p = P(s[l++]);
if(flag[p]==1) flag[0]--;
flag[p]--;
if(flag[0]>=3&&r-l+1>=L){
cnt+=min(n-r+1,R-L+1);
}
}
cout<<cnt<<endl;
return 0;
}
题目链接
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
瑟提是一个拳击高手,蓄意轰拳是他一个非常强大的技能。
一天,他碰到个N个敌人。因为敌人都排好队了,所以,我们可以将问题简单化,瑟提每次蓄意轰拳可以使连续3个位置上的敌人遭到 1 点伤害。(也可以只对 一个敌人 或者 相邻的两个敌人 造成伤害)
当敌人的血量变为 0 时,视为敌人被消灭(但敌人的位置仍然保留)。
此外瑟提还具有一个大招——叹为观止!(只能使用一次)
他可以让两个相邻的敌人直接消灭(只有一个敌人也可以使用,敌人位置仍然保留)。
瑟提不想浪费体力,所以他只会使用蓄意轰拳和叹为观止。
请问,瑟提最少需要使出多少次蓄意轰拳,才能够消灭所有敌人?
如果瑟提太晚回家,他的老妈会担心他,为了不让瑟提的老妈担心,瑟提请聪明的你来帮助他!
输入描述
第一行一个数n(1 ≤ n ≤ 106 ) ,分别表示敌人的数量
第二行共 n 个整数,第i个整数表示a i (0 ≤ ai≤ 109 )表示第i只敌人的血量
输出描述
共一个数,表示瑟提最少需要使出蓄意轰拳的次数
示例1
输入:
3
66 66 1
输出:
1
说明:
对1号敌人和2号敌人使用叹为观止,对3号敌人使用一次蓄意轰拳。
示例1
输入:
2
100 600
66 66 1
输出:
0
说明:
只需对1号敌人与2号敌人使用叹为观止,无需使用蓄意轰拳。
解题思路
ms[]是前缀和,ks[]是后缀和
枚举ms[i-1]+ks[i+2],代表干掉i和i+1后需要的次数
代码
#include
using namespace std;
const int N = 1e6+10;
int a[N],b[N];
long long ms[N],ks[N];
int main(){
int n;
cin>>n;
for(int i = 1;i<=n;++i){
cin>>a[i];
b[i] = a[i];
}
if(n<=2){
cout<<0<<endl;
return 0;
}
for(int i = 1;i<=n;++i){
if(a[i]>0){
ms[i]=a[i]+ms[i-1];
a[i+1]-=a[i];
a[i+2]-=a[i];
}
else
ms[i]=ms[i-1];
}
for(int i = n;i>=2;--i){
if(b[i]>0){
ks[i]=b[i]+ks[i+1];
b[i-1]-=b[i];
b[i-2]-=b[i];
}
else
ks[i]=ks[i+1];
}
long long ans = ms[n];
for(int i = 1;i<=n;++i){
ans = min(ms[i-1]+ks[i+2],ans);
}
cout<<ans<<endl;
return 0;
}
这次学校算法工作室招新赛,虽然题目不难,而且大部分题也学过相关算法,可还是只做出了寥寥几题〒▽〒
对不起(鞠躬)刷题的事情下次一定(
第一次写博客,如有错误请在评论区指正
都看到这里了,不如点个赞鼓励一下作者吧( ̄﹃ ̄)