2020-3-14 acm训练联盟周赛Preliminaries for Benelux Algorithm Programming Contest 2019 解题报告+补题报告
Posted rzqmzl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2020-3-14 acm训练联盟周赛Preliminaries for Benelux Algorithm Programming Contest 2019 解题报告+补题报告相关的知识,希望对你有一定的参考价值。
2020-3-15比赛解题报告+2020-3-8—2020-3-15的补题报告
2020-3-15比赛题解
训练联盟周赛Preliminaries for Benelux Algorithm Programming Contest 2019
A建筑(模拟)
耗时:3ms 244KB
建筑
你哥哥在最近的建筑问题突破大会上获得了一个奖项
并获得了千载难逢的重新设计城市中心的机会
他最喜欢的城市奈梅根。由于城市布局中最引人注目的部分是天际线,
你的兄弟已经开始为他想要北方和东方的天际线画一些想法
让奈梅根去看看。然而,他的一些提议看起来相当古怪,你是
开始怀疑他的设计是否可行。
为了他的设计,你哥哥在这个城市上安装了一个R × C网格。城市的每个单元都将
包含一定高度的建筑。东方的天际线是由1970年最高的建筑所呈现的
每一排R,和北方的地平线是由每一个C中最高的建筑给出的
列。
只有当存在某种方式时,你哥哥的一副天际线图才是可能的
将建筑高度指定给网格单元,以使生成的天际线与这些天际线匹配
图纸。
图A1显示了一个可能的城市,其北部和东部的天际线与中给出的完全相同
第一个样本的输入。
1 2 3 4
0 1 2 3
1 2 1 1
1 0 1 1
图A1:示例城市显示示例1有一个有效的解决方案。
投入
第一行包含两个整数1 ≤ R,C ≤ 100,行数和列数
在格子里。
第二行由R个整数x 1组成,...,x R描述东部地平线(0 ≤ x i ≤ 1000
对于所有I)。
第三行由C整数y 1组成,...,y C描述北部地平线(0 ≤ y j ≤ 1000
对于所有j)。
输出
如果存在一个城市设计,则输出一行可能包含的字符串
指定的天际线,否则不可能。
/*判断每个数组最大值相等即可*/
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 10000
using namespace std;
int main()
{
int R,C;
while(scanf("%d%d",&R,&C)!=EOF)
{
int D[N],B[N],j,i;
for(i=0;i<R;i++)
{
scanf("%d",&D[i]);
}
for(i=0;i<C;i++)
{
scanf("%d",&B[i]);
}
sort(D,D+R);
sort(B,B+C);
int f=0;
if(D[R-1]!=B[C-1]){f=1;}
if(f==1){printf("impossible ");}
else if(f==0){printf("possible ");}
}
return 0;
}
感想
最开始提交的几次是对题意不理解,其实是个模拟,只要判断每个数组最大值是否相等即可,sort函数真香。
B括号序列
建议:时限 1S、内存 64M
两个好朋友,埃迪·约翰和克里斯·克罗斯将出席
括号是完美会议。他们全心全意
同意会议的主要信息,他们是
对他们学习到的所有关于支架的新知识感到高兴。
其中之一是括号序列。如果你想做一个
用+和×,你通常是这样写的:
(2 × (2 + 1 + 0 + 1) × 1) + 3 + 2。
括号仅用于分组乘法和加法
一起祈祷。这意味着你可以删除所有的歌剧-
tor,只要你记得加法是用于数字的
任何括号外!然后,可以将括号序列缩短为
(2 ( 2 1 0 1 ) 1 ) 3 2。
这要好得多,因为它节省了编写所有这些操作符的时间。阅读支架se-
后果也很简单。假设您有以下括号序列
5 2 ( 3 1 ( 2 2 ) ( 3 3 ) 1)。
你从加法开始,所以这和下面一样:
5 + 2 + ( 3 1 ( 2 2 ) ( 3 3 ) 1)。
你知道括号里是乘法,所以这等于
5+2+(3×1×(2 ^ 2)×(3 ^ 3)×1)。
然后还有另一层括号:将乘法运算分组,
所以操作必须是加法。
5+2+(3×1×(2+2)×(3+3)×1)= 5+2+(3×1×4×6×1)= 5+2+72 = 79。
由于括号序列比带有运算符的普通表达式容易得多,因此应该如此
容易评估一些大的。我们甚至会允许你写一个程序来实现它
你。
请注意( )不是有效的括号序列,也不是任何有效括号序列的子序列。
投入
一行包含一个1 ≤ n ≤ 3 10 5的整数。
一行由n个记号组成,每个记号要么是(,),要么是一个0 ≤ x < 10 9 + 7的整数。
保证标记形成一个括号序列。
6问题B:括号序列
输出
输出给定括号序列的值。因为这个可能很大,你应该
以10 ^ 9+7为模打印。
样本输入1样本输出1
2
2 3
5
样本输入2样本输出2
8
(2 ( 2 1 ) ) 3
9
样本输入3样本输出3
4
(12 3)
36
样本输入4样本输出4
6
(2 ) ( 3)
5
样本输入5样本输出5
6
((2 3))
5
样本输入6样本输出6
11
1 ( 0 ( 583920 ( 2839 82)))
/*给你一串字符串,最外面全用+,一层括号用*,两层用+,三层用*,以此类推*/
代码(题解)
Std:https://pasteme.cn/26957
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>
typedef long long LL;
using namespace std;
const long long mod = 1e9 + 7;
int n;
char s[15];
struct node/*结构体*/
{
int val;
node* next;
node(int w, node *n){
val = w;
next = n;
}
};
class Stack{
public :
int sz;
node* head;
Stack(){
head = NULL;
sz = 0;
}
bool empty(){
return !sz;
}
int top(){
if(!empty()) return head->val;
return 0;
}
node *push(int val){
head = new node(val, head);
sz++;
return head;
}
void pop(){
if(empty()) return ;
node *tp = head;
head = head->next;
sz--;
delete tp;
}
int size(){
return sz;
}
}sk[300005];
int change(char s[]){
int res = 0;
int len = strlen(s);
for (int i = 0; i < len; i++) res = res * 10 + s[i] - ‘0‘;
return res;
}
int main()
{
//freopen("in.txt", "r", stdin);/*打开文件*/
//freopen("out.txt", "w", stdout);
scanf("%d", &n);
int cnt = 0;
for (int i = 1; i <= n; i++){
scanf("%s", s);
if(s[0] == ‘(‘) cnt++;
else if(s[0] == ‘)‘){
if(cnt & 1){
LL ans = 1;
while(sk[cnt].size()) ans = ans * sk[cnt].top() % mod, sk[cnt].pop();
cnt--;
sk[cnt].push(ans);
}else{
LL ans = 0;
while(sk[cnt].size()) ans = (ans + sk[cnt].top()) % mod, sk[cnt].pop();
cnt--;
sk[cnt].push(ans);
}
}else{
sk[cnt].push(change(s));
}
}
LL ans = 0;
while(sk[0].size()) ans = (ans + sk[0].top()) % mod, sk[0].pop();
printf("%lld ", ans);
return 0;
}
感想:
看了别人的题解,有很多自己还未接触的事物,一些函数和算法,自己需要加强了。
C峡谷穿越
建议:时限 5S、内存 64M
桥梁和通道创建者负责在当地开辟新的道路
群山。他们批准了你在你最喜欢的峡谷修建一条新路线的计划。
当你意识到自己没能走上这条美丽的新道路时,你狂热地开始工作
考虑附近河流的流量:峡谷被淹没了!显然这种情况发生过一次
每一轮蓝月,都让道路的某些部分无法到达。因为这个,你想要
建立一条路径,使路径上的最低点尽可能高。你快
回到村子里,用你所有的钱去买吊桥。你打算用这些来
绕过峡谷的最低处。
1 1 3
3 3 3
0 0 0
2 2 1
1 2 1
(1)
B
(2)
B
图C1:峡谷和两条可能的路径,最小高度为1,样本输入为2。最好的
指示桥梁。
你的峡谷地图由一个矩形网格组成,每个网格包含一个数字
该单元的地形高度。这条小路将从峡谷的南边开始
(地图底部)到北边(地图顶部),穿过一个相连的
细胞序列。当且仅当两个单元共享一条边时,才认为它们是连接的。在
特别地,两个对角接触的单元不被认为是连接的。这意味着
对于不在地图边缘的任何单元,有4个其他单元与之相连。的左边
图C1包含第一个样本输入的映射。
穿过峡谷的路径可以从网格的任何底部单元开始,结束于
顶部塔中的任何一个单元,如C1中右边的两条路径。最低高度为
由路径经过的任何单元的最低高度给出。每座桥都可以
用来穿过一个牢房。然后,在计算时不考虑该单元格
路径的最小高度。请注意,允许链接多个桥来使用它们
跨越多个细胞,
给定峡谷的地图和可用的桥梁数量,找出最低高度
最佳路径。
问题八:穿越峡谷
1 1 3
3 3 3
0 0 0
2 2 1
1 2 1
(1)
B
(2)
B
图2:峡谷和样本输入的最佳路径2。
投入
包含三个整数的单行:1 ≤ R ≤ 1000和1 ≤ C ≤ 1000,大小为
映射,0≤K≤R1,您可以建立的桥的数量。
接下来是R行,每一行都包含C个整数。第I行的第j个整数
对应于点(I,j)处峡谷的高度0≤h1,j ≤ 10 9。第一行
相当于峡谷的北缘,南缘的最后一条线。
输出
输出单个整数,最佳路径的最低高度。
样本输入1样本输出1
5 3 1
1 1 3
3 3 3
0 0 0
2 2 1
1 2 1
2
样本输入2样本输出2
5 3 3
2 1 1
2 1 1
1 1 1
1 1 2
1 1 2
2
样本输入3样本输出3
3 2 2
1 1
4 4
1 2
4
/*找最小值,起初自己遍历了一遍一直出错,现参考的题解*/
代码(题解代码部分)
Std:https://pasteme.cn/26958
int bfs(int val){/*题解中代码优化用的bfs,因为多种解答,还有单元格重复*/
memset(vis, 0, sizeof(vis));/*清空*/
queue<node> q[k + 2];
for (int i = 1; i <= m; i++) vis[n][i] = true, q[mp[n][i] < val ? 1 : 0].push(node(n, i));
for (int i = 0; i <= k; i++){
while(q[i].size()){
node front = q[i].front();
if(front.x == 1) return 1;
q[i].pop();
for (int j = 0; j < 4; j++){
int x = front.x + d[j][0], y = front.y + d[j][1];
if(x < 1 || x >= n || y < 1 || y > m) continue;
if(!vis[x][y]){
vis[x][y] = true;
q[mp[x][y] < val ? i + 1 : i].push(node(x, y));
}
}
}
}
return 0;
}
struct node
{
int x, y;
node() {}
node(int x, int y) : x(x), y(y) {}
};
感想
自己起初做题对于条件考虑太少,把题意曲解了,漏了很多条件,在遍历时其实就已经超时了,通过bfs代码的优化后大致对自己的代码进行修改,结果依旧不对,于是就按他人题解为模板来学习。
D欺骗性骰子
建议:时限 1S、内存 128M
最近你们镇上到处都是骗子
不知情的游客和他们玩一个简单的骰子游戏
钱。游戏的工作原理如下:给定一个n面骰子,
其边长为1,2,...,n点,和一个正整数k。你
然后掷骰子,然后必须做出选择。选项1是
停止滚动。选项2是重新滚动芯片,但有限制
模具总共只能滚动k次。你的分数是
你最后一卷的点数。
很明显,骗子比骗子更擅长这个游戏
游客是。你,对抗普罗巴战斗的骄傲支持者
动荡的灾难,决定打击这个问题不是通过取缔骗子,而是通过武装
有信息的游客。
你制作小册子,游客可以在上面找到许多价值的最高期望值
你可以肯定,如果游客是骗子,他们很快就会停止诈骗
比他们准备得更好!
传单的布局已经完成,你已经建立了分销渠道。剩下的就是
要做的是计算放在小册子上的数字。
给定骰子的边数和允许滚动的次数,计算
最佳游戏时的预期(即平均)分数。
投入
两个整数1 ≤ n ≤ 100的单行,芯片的边数,以及
1 ≤ k ≤ 100,模具可以轧制的次数。
输出
以最佳方式演奏时输出预期得分。你的答案应该是绝对的或
相对误差至多为10-7。
样本输入1样本输出1
1 1 1
样本输入2样本输出2
2 3 1.875
样本输入3样本输出3
6 2 4.25
样本输入4样本输出4
8 9 7.268955230712891
/*盼期望分值*/
代码(原题解代码,自己的一直输出问题)
Std:https://pasteme.cn/26959
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>
typedef long long LL;
using namespace std;
int n, k;
int p[10005];
int main()
{
scanf("%d %d", &n, &k);
double ans = 0;
for (int i = n; i >= 1; i--) p[i] = p[i + 1] + i;
for (int i = 1; i <= k; i++){
if(i == 1){
ans = 1.0 * p[i] / n;
}else{
ans = 1.0 * (p[(int)floor(ans) + 1] + floor(ans) * ans) / n;
}
}
printf("%.7lf ", ans);/*保留格式之前自己一直没好好注意*/
return 0;
}
感想
ans = 1.0 * (p[(int)floor(ans) + 1] + floor(ans) * ans) / n;
新知识get√:floor:“向下取整”,或者说“向下舍入”、“向零取舍”,即取不大于x的最大整数,与“四舍五入”不同
E. Exits in Excess
建议:时限 2S、内存 128M
你拥有一家迪斯科舞厅,名为“布吉永远坚持俱乐部”。
该俱乐部因其多个相互连接的房间而闻名
扭身大喊大叫。房间和走廊之间
它们形成一个迷宫般的结构,为你增加额外的奖励
把所有的走廊都弄成了单行道。然而,事实是
不是每个人都像你一样对你的俱乐部满意。
最近消防安全检查员来了,他们
他们所看到的并不好笑:如果发生火灾
其中一个房间,人们很难找到
火从出口出来,甚至可能开始绕圈跑!他们完全发现了这一点
不可接受,命令你尽快改进。他们坚持要你
必须确保没有人可以在俱乐部里跑来跑去
房间之间的走廊。
另一方面,你想保持房间的吸引力。你不想
移走太多的走廊,因为这样人们就不会再去你的俱乐部了。你决定
最多一半的走廊会被拆除。
根据俱乐部的布局,移除最多一半的走廊,这样就没有自行车了。
投入
一条线包含1 ≤ n ≤ 10 5的房间数量和走廊数量
0 ≤ m ≤ 2 10 5。
然后跟随m行,每一行包含两个不同的基于1的整数u和v,表示
从u房间到v房间的走廊。没有从房间到房间本身的走廊,也没有
从一个房间到另一个房间会有不止一条走廊吗?
输出
在第一行,打印一个整数0 ≤ r ≤ m/2,走廊的数量为
移除。
然后打印包含需要删除的走廊的基于1的索引的r行
以确保舞者不再在迪斯科舞厅转圈。
如果有多个有效的解决方案,您可以输出其中任何一个。
样本输入1样本输出1
2 2
1 2
2 1
1
2
12问题五:超额退出
样本输入2样本输出2
3 3
1 2
2 3
3 1
1
1
样本输入3样本输出3
4 5
1 2
1 3
3 2
2 4
3 4
0
样本输入4样本输出4
4 5
1 2
2 3
2 4
3 1
4 1
2
4
5
样本输入5样本输出5
4 3
1 2
2 3
3 4
1
2
/*题解做法*/
/*给定 n, 求 n=m^2-k^2。
1. 对于 n 为奇数时,有(x+1)^2-x^2=2x+1。
2. 对于 n 为 4 的倍数时,有(x+2)^2-x^2=4(x+1)。*/
代码:(题解代码部分)
Std:https://pasteme.cn/26960
scanf("%d %d", &n, &m);
for (int i = 1, u, v; i <= m; i++){
scanf("%d %d", &u, &v);
if(u < v) v1.push_back(i);
else v2.push_back(i);
}
if(v1.size() > v2.size()){
printf("%d ", v2.size());
for (auto x : v2) printf("%d ", x);
}else{
printf("%d ", v1.size());
for (auto x : v1) printf("%d ", x);
}
return 0;
感想
自己没做出来,是在读题上就停止了,对题意没能理解,n=m^2-k^2没能打到;多少是自己想的太少外加没能理解题意,对奇数和偶数都没能判断,自闭了自闭了。。。
F建筑的平面图
建议:时限 1S、内存 128M
在flickr上通过Gisela Giardino
你是一名建筑师,刚刚被任命为
建造一个新的游泳馆。这些背后的组织
计划已经获得了建造游泳池和冲浪的资金
他们想要多大就多大,但不幸的是
他们找不到任何人愿意付地板费-
绕过游泳池。他们决定支付地砖的费用
从他们自己的口袋里。因为这已经花费了
他们有一条胳膊和一条腿,他们想让你使用所有的地板
你提议的计划中的瓦片。
作为一名建筑师,你关心美学。你认为它是
绝对重要的是游泳池和游泳池-
圆形建筑是完美的正方形。这引发了一个-
有趣的问题:你如何确保正方形是有保证的,同时又不变形
使用组织购买的所有地砖?
给定瓷砖的数量n,找出建筑边的长度m和长度
如果没有合适的m和,则无法打印
k存在。
投入
一行包含一个1 ≤ n ≤ 10 9的整数。
输出
打印两个非负整数m,k,使n = m ^ 2-k ^ 2,如果没有,则打印不可能
整数存在。如果有多个有效的解决方案,您可以输出其中任何一个。
样本输入1样本输出1
7 4 3
样本输入2样本输出2
10不可能
样本输入3样本输出3
15 4 1
代码:
运行超时:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 10000
using namespace std;
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int i,j;
int k,m;
int f=0;
if(n==0){printf("0 ");}
else if(n==1){printf("1 ");}
else if(n>1&&n<=1000000)
{
for(i=0;i<n;i++)
{
for(j=0;j<=i;j++)
{
int c;
c=pow(i,2)-pow(j,2);
if(c==n)
{
f=1;
m=i;
k=j;
break;
}
}
if(f==1){break;}
}
}
else if(n>1000000&&n<100000000)
{
for(i=1000;i<sqrt(n)+1;i++)
{
for(j=0;j<=i;j++)
{
int r;
r=pow(i,2)-pow(j,2);
if(r==n)
{
f=1;
m=i;
k=j;
break;
}
}
if(f==1){break;}
}
}
else if(n>=100000000&&n<1000000000)
{
for(i=10000;i<sqrt(n)+1;i++)
{
for(j=0;j<=i;j++)
{
int r;
r=pow(i,2)-pow(j,2);
if(r==n)
{
f=1;
m=i;
k=j;
break;
}
}
if(f==1){break;}
}
}
if(f==1){printf("%d %d ",m,k);}
else {printf("impossible ");}
}
return 0;
}
题解
Std:https://pasteme.cn/26961
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>
typedef long long LL;
using namespace std;
LL n;
int main()
{
scanf("%lld", &n);
if(n & 1) printf("%lld %lld ", n / 2 + 1, n / 2);
else if(n % 2 == 0 && n % 4) printf("impossible ");
else printf("%lld %lld ", (n - 4) / 4 + 2, (n - 4) / 4);
return 0;
}
/**/
感想:
题解的方法很好,但是自己没想到,到最后几分钟还在想着开方来优化缩短时耗,结果越改越大。
G
耗时:3ms,244KB
您好!
现在Snapchat和弹弓已经是2018年了
世界上的青少年都转向了新的热点
名为BAPC的应用程序(双向和私人通信)
阳离子)。这款应用的社交规则比
以前的迭代。例如,如果有人说好-
再见,使用稍后!,另一个人预计会重新
与鳄鱼同游!。你不能记录所有的事情
这些社会惯例,并决定自动化任何必要的
sary的回答,从最重要的一个开始
问候。当你的对话伙伴开始
他...嘿,你得用“喜”来回应...嗯,
但是使用两倍的e!
给定一串形式他...长度最多为1000埃,
打印您将回复的问候语,包含两次
和e一样多。
投入
输入由一行包含指定的单个字符串组成,长度至少为
3,最多1000。
输出
输出所需的响应。
样本输入1样本输出1
嘿heey
样本输入2样本输出2
heeeeeeeeeey
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 10000
using namespace std;
int main()
{
int n,i,j;
char s[10000];
while(scanf("%s",s)!=EOF)
{
n=strlen(s);
int m;
m=n-2;
printf("h");
for(i=0;i<2*m;i++)
{
printf("e");
}
printf("y ");
}
return 0;
}
感想:
之前在这道题上还想多了,差点陷入判断大坑。
H
六角车
建议:时限 1S、内存 32M
这是游戏之夜,爱丽丝和鲍勃正在下棋。下棋赢了鲍勃几次后,
爱丽丝建议他们应该玩一种叫做六边形象棋的象棋变体。虽然
现在很少玩游戏了,爱丽丝非常了解游戏规则,并获得了a
六边形棋盘来自她订阅的《玩的奇异物品》杂志
象棋。
图H.1:六边形棋盘的场名和白勺方向
走开。
上图所示的六边形棋盘由91个六边形格子组成
边长为6的六边形,如上图所示。董事会分为
11列,每列称为一个文件,文件从左到右标记为a到k。它也是
分成11个v形行,每个行称为一个等级,从下到上标记为1到11
顶部。然后,文件x和等级y中的唯一单元由坐标xy表示。例如,
等级11只包含一个单元格f11,等级7完全由黑人玩家占据
小卒。
爱丽丝首先解释了所有的碎片是如何移动的。最简单的一件是车,它
可以在直线上向下列任意方向移动任意正的步数
它的6个相邻单元格,如右图所示。鲍勃立即意识到
六角形车已经比普通的象棋车更难操作了。
为了攻击对手的棋子,知道他的车可以攻击哪些细胞是有用的
移动到攻击对方。这些细胞越多,就越多
他的车现在的位置很有价值。然而,计算这个数字太多了
给鲍勃。在输了这么多局常规象棋后,爱丽丝允许鲍勃使用一个程序
协助他安置车。当爱丽丝解释游戏的其余部分时,你开始忙于编码。
问题16:六边形车
作为一个小的简化,鲍勃将计算他的车可以移动到
目的地细胞假设没有其他的棋子在棋盘上,甚至没有他想要的棋子
进攻。
投入
输入由一条线组成,包含六边形上的两个不同坐标
棋盘,你的车的当前位置和你想攻击的棋子。
输出
输出一个整数,即车从当前位置移动到
假设没有其他棋子,它要攻击的棋子的位置正好在两个步骤中
棋盘上的棋子。
样本输入1样本输出1
c4 h4 6
样本输入2样本输出2
a1 a2 5
/*给定起始位置的行(数字 1~11)和列(字母 a~k)和末位置的行和列,求两步(一步的
长度不一定是 1)走到末位置的中间点的数量。*/
代码:(部分题解原代码)
Std:https://pasteme.cn/26962
bool solve(char sl, int sr, char el, int er){
if(sl == el) return sr != er;
if(sl > ‘f‘) sr += sl - ‘f‘;
if(el > ‘f‘) er += el - ‘f‘;
if(sr == er) return true;
if(el - sl == er - sr) return true;
return false;
}/*判断*/
for (int i = ‘a‘; i <= ‘k‘; i++){
int num = 11 - abs(‘f‘ - i);
for (int j = 1; j <= 11; j++){
if(j > num) break;
if(solve(c1, x, i, j) && solve(i, j, c2, y)) ans++;
}
}
感想:
当时没能读懂题意纠结于每一步的单位,后参照题解,并应用题解函数来做判断,但是自己代码优化不好,耗时还是很长,于是这里代码用的原题解代码,自己对一些函数接触过少,不是不会用,就是用的过程会出错。函数还需多加练习。
I
调查一
建议:时限 1S、内存 32M
竞赛中人为问题局希望你解决以下问题:
给定n个正整数a 1,...,a,n,最大值是多少
?
a 2
1 + + a
2
k
?
(a k+1 + + a n)?
投入
包含整数2 ≤ n ≤ 10 6的单行。
然后跟随n行,其中I包含整数1 ≤ a i ≤ 100。
输出
输出给定表达式的最大值。
样本输入1样本输出1
5
2
1
4
3
5
168
样本输入2样本输出2
2
1
1
1
样本输入3样本输出3
10
8
5
10
9
1
4
12
6
3
13
10530
代码:
/*比赛中过样例的错误代码#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 1000005
using namespace std;
int a[N];
int main()
{
int n;
while(~scanf("%d",&n))
{
if(n==0){break;}
int c;
c=n-1;
int i,j;
long long M;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
M=0;
while(c--)
{
int sum=0;
for(j=0;j<=c;j++)
{
sum+=pow(a[j],2);
}
int num=0;
for(i=n-1;i>c;i--)
{
num+=a[i];
}
long long Y;/*递归算*/
Y=num*sum;
if (Y>M){M=Y;}
}
printf("%lld ",M);
}
return 0;
}*//比赛期间还出现了段错误**/
原题解代码Std:https://pasteme.cn/26963
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>
typedef long long LL;
using namespace std;
int n, a[1000005];
LL l[1000005], r[1000005];
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= n; i++) l[i] = l[i - 1] + a[i] * a[i];
for (int i = n; i >= 1; i--) r[i] = r[i + 1] + a[i];
LL ans = 0;
for (int i = 1; i < n; i++) ans = max(ans, l[i] * r[i + 1]);
printf("%lld ", ans);
return 0;
}
/**/
感想:
看了原题解max函数解决了很多麻烦,经过检查,自己在细节上经常出错,感觉编程不是为了样例编的。条件和情况要考虑全面,一定要读好题中范围和条件。
j
混乱的旅程
建议:时限 1S、内存 32M
和一些朋友一起,你正计划去美丽的正宗公园度假
中间。在那里,你想尽可能多地参观公园。作为
准备工作你和你最好的朋友决定制作一张地图
公园,它们之间的道路,以及这些道路的长度。为了确保来访者能够
公园中心不会无休止地在华丽的公园中穿梭,公园之间的路线
公园是单向的,而且是这样建造的,不可能不止一次去公园
(也就是说,相应的图是非循环的)。你们花了一整天来创造一个
令人难以置信的详细和公认的相当大的公园中心地图。
1
2 3
4
2 4
6
4
4
图1:对应于样本输入1的公园地图。
第二天灾难降临:你的朋友高兴地宣布他摆脱了烦恼-
一些地图!相反,他决定用一个只包含平均值的简单表格来代替它
公园之间的距离,平均衡量每条路线。因此,他会给你一个平均值
公园1和公园4之间的距离为8,如图1所示,因为有3条路径及其
平均长度为(6+8+10)/3 = 8。你感到被打败了,你害怕做出
地图又翻了一遍。也许尝试使用平均距离表会更容易
你的朋友为了重建原始地图。你记得的一件事是
地图上的道路从来都不是低效的。如果两个公园之间有一条直路,
那么每一条经过至少另一个公园的路径都是严格意义上的更长。这一条件适用于
第一个样本输入,因为例如,从1到4的道路具有长度6,该长度较短
比从1到4的任何其他路径的长度都长。
给定公园间平均距离的输入,输出原始地图:加权
这些平均距离所代表的有向无环图。
投入
第一行包含整数1 ≤ n ≤ 100,即顶点数(公园)。
接下来的n条线包含从顶点I到顶点j的平均距离作为第j个数字
在第I条线上,如果从顶点I到顶点j没有路径,则为1。所有距离
为1或非负整数,最多10 ^ 15。
关于地图(原始图形),您知道以下事实:
问题J:混乱的旅程19
一旦离开公园,就没有办法沿着道路返回公园。也就是说,
该图是非循环的。
原始图表中的道路长度都是整数。
在任何两个公园之间,最多有1000条不同的路径可供您选择
另一个。
直路总是有效的:如果有从I号公园到j号公园的直路,每
从I到j其他路径严格来说比直路长。
输出
打印n行,每行包含n个整数。第一行的第一个数字应该是正数
从顶点I到顶点j的边的长度,如果没有这样的边,则为1。这是有保证的
存在一个解决方案。
样本输入1样本输出1
4
0 2 5 8
-1 0 4 8
-1 -1 0 4
-1 -1 -1 0
-1 2 4 6
-1 -1 4 -1
-1 -1 -1 4
-1 -1 -1 -1
样本输入2样本输出2
6
0 -1 48 -1 132 -1
24 0 84 36 153 108
-1 -1 0 -1 84 -1
-1 -1 60 0 116 72
-1 -1 -1 -1 0 -1
-1 -1 -1 -1 96 0
-1 -1 48 -1 -1 -1
24 -1 -1 36 -1 -1
-1 -1 -1 -1 84 -1
-1 -1 60 -1 36 72
-1 -1 -1 -1 -1 -1
-1 -1 -1 -1 96 -1
/*给定数组 a,求公式的最大值。
求 a 数组平方的前缀和和求 a 数组后缀和,遍历一遍即可。*/
代码:
(原题解代码)
Std:https://pasteme.cn/26964
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>
typedef long long LL;
using namespace std;
int n, in[105], toposort_v[105], toposort_p[105], num[105][105];
LL dag_ans[105][105];
LL dag_ave[105][105], dag_new[105][105];
int main()
{
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
scanf("%d", &n);
for (int i = 1; i <= n; i++){
for (int j = 1; j <= n; j++){
scanf("%lld", &dag_ave[i][j]);
if(dag_ave[i][j] > 0) in[j]++;
}
}
// toposort to new dag
queue<int> q;
int cnt = 0;
for (int i = 1; i <= n; i++) if(!in[i]) q.push(i), toposort_v[++cnt] = i;
while(q.size()){
int u = q.front();
q.pop();
for (int v = 1; v <= n; v++){
if(dag_ave[u][v] > 0){
in[v]--;
if(in[v] == 0) q.push(v), toposort_v[++cnt] = v;
}
}
}
for (int i = 1; i <= n; i++) toposort_p[toposort_v[i]] = i;
// new dag
for (int i = 1; i <= n; i++){
for (int j = 1; j <= n; j++){
dag_new[i][j] = dag_ave[toposort_v[i]][toposort_v[j]];
}
}
// orginal ans_dag
memset(dag_ans, -1, sizeof(dag_ans));
for (int i = 1; i < n; i++){
if(dag_new[i][i + 1] > 0) dag_ans[i][i + 1] = dag_new[i][i + 1], num[i][i + 1] = 1;
}
for (int len = 2; len <= n; len++){
for (int i = 1; i + len <= n; i++){
int j = i + len;
// i -> k -> j ways‘ number and weight
LL sum = 0;
for (int k = i + 1; k < j; k++){
if(dag_ans[i][k] > 0 && num[k][j] > 0){
num[i][j] += num[k][j];
sum += dag_ans[i][k] * num[k][j] + dag_new[k][j] * num[k][j];
}
}
// if add a path, ave = (sum + x) / (num[i][j] + 1), x is new path‘s weight
LL x = dag_new[i][j] * (num[i][j] + 1) - sum;
if((num[i][j] == 0 && dag_new[i][j] > 0) || (num[i][j] && x > 0 && dag_new[i][j] > x)){
dag_ans[i][j] = x;
num[i][j]++;
}
}
}
for (int i = 1; i <= n; i++){
for (int j = 1; j <= n; j++){
int x = toposort_p[i], y = toposort_p[j];
printf("%lld%c", dag_ans[x][y], j == n ? ‘ ‘ : ‘ ‘);
}
}
return 0;
}
感想:
比赛期间由于到最后时间不多了,没能读懂题意,后来比赛完了,结合题解理解有了一定的认识。不只是简单的求最大,里面还有连线等细节,依旧是读题能力,是自己接触题型太少了。
k背包包装
建议:时限 1S、内存 128M
度假最困难的事情之一
确保你的行李不超过最大限额
重量。你,背包客协会主席
包装手提行李,正面临着这个问题。
你要和你的一个朋友去度一个愉快的假期,
但是现在你大部分时间都在沮丧中度过
试图打包你的背包。为了优化这一点
过程中,你和你的朋友已经独立着手
试图找到更好的打包方式。
一段时间后你会有一个重大突破!你设法解决了这个难题-
多项式时间内的sack问题,处处挑战期望。你对什么不感兴趣
任何理论上的应用,所以你立刻回到你朋友的公寓
现在快速打包你的背包。
当你到达那里时,你会发现你的朋友已经有了自己的解决办法,那就是
列举所有可能的包装。这意味着你可能想带的所有物品都是
分散在整个公寓里,要花很长时间才能拿到所有的东西
一起回来。
幸运的是,你可以利用你朋友所做的工作。对于每个可能的项目子集
你可能会带来,她已经记下了这些物品的总重量。唉,她做到了
不要写下哪些项目是这个总数的一部分,所以你不知道哪些项目有贡献
每一个总重量。如果项目的原始权重形成集合(a 1,...,n ) of
非负整数,那么你的朋友已经写下了多重集
s?(a 1、...,a n)?:=
。
例如,如果你的朋友有两个项目,这两个项目的权重是2,3,那么
你的朋友写下了
0,对应于空集{ };
2,对应于子集{ 2 };
3,对应于子集{ 3 };
5,对应于子集{2,3}。
您希望重建所有单个项目的权重,以便可以开始使用
背包算法。可能发生了这样的情况,你的朋友在添加所有内容时犯了错误
这些权重,所以她的列表可能不一致。
问题K:背包包装21
投入
一行包含单个整数1 ≤ n ≤ 18项目数。
2 n行,每一行包含一个整数0 ≤ w ≤ 2 28,即子集的组合权重
所有的物品。每个子集只出现一次。
输出
输出非负整数a 1,...n条线上的n,以非递减顺序排列,使得S?(a 1、...,a n)?=
{b 1,...,b 2 n },前提是存在这样的整数。否则,输出一行,包含
不可能。
样本输入1样本输出1
1
0
5
5
样本输入2样本输出2
3
7
5
2
4
1
6
3
0
1
2
4
样本输入3样本输出3
2
0
1
2
4
不可能的
样本输入4样本输出4
2
0
1
1
2
1
1
给你n件物品和他们的重量和所有组合,求是否存在这n件物品的重量,满足这些组合
代码,原题解
Std:https://pasteme.cn/26965
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>
typedef long long LL;
using namespace std;
int n, ans[25];
multiset<int> s;
int main()
{
scanf("%d", &n);
for (int i = 0, x; i < (1 << n); i++) scanf("%d", &x), s.insert(x);
int cnt = 0;
for (int i = 1; i <= n; i++){
if(s.size() < 2) break;
cnt++;
int x = *prev(s.end()) - *prev(prev(s.end()));
ans[i] = x;
for (auto it = s.begin(); it != s.end(); it++){
int y = *it;
auto p = s.upper_bound(x + y);
p = prev(p);
if(p == s.end() || p == it || *p != x + y){
printf("impossible ");
return 0;
}
s.erase(p);
}
}
if(s.size() != 1 || *s.begin() != 0 || cnt < n) printf("impossible ");
else for (int i = 1; i <= n; i++) printf("%d ", ans[i]);
return 0;
}
感想:
自己后来打了一次遍历找可能情况,但是超时了,一个是代码优化,另一方面是函数调用需要加强。
L救生员
建议:时限 1S、内存 32M
通过约书亚·林奇在flickr
救生员有一项非常重要的工作。他们阻止人们
避免溺水,并允许每年数百万人
体验水的乐趣。你是救生员之一,
你对待工作非常认真。如果法规符合
你,每个人在水里都会穿救生衣,
这就是为什么你是浮力积极分子推广活动的一部分
改变。由于你的不断游说,池在
你是救生员,决定再雇一名救生员。
你对当地游泳池安全措施的加强非常满意。
你和新救生员相处得很好,但是你发现你还没有准备好
他的到来;在一起工作的第一天,你很难搞清楚
谁应该看哪个游泳运动员。这是完全不可接受的,并可能导致
伤亡人数!你立即开始解决这个问题:遵循“共享”的咒语
“责任不等于责任”,你试图把游泳池里的人一分为二
分组如下:任何游泳者都是最接近这个游泳者的救生员的责任。
因此,知道所有游泳者的确切位置,你和你的同事都会找到一个位置
以至于你们两个都要为同样数量的游泳者负责。此外,
你最多想要一个距离你和你的同事相等的游泳者。
这位游泳运动员兼当救生员。
因为你和你的同事都是出色的短跑运动员,你不在乎实际距离
在你和游泳者之间,只是游泳者被很好地分成两等份
大小团体。
投入
第一行包含一个整数2 ≤ n ≤ 10 5,即游泳人数。
接下来的n行包含两个整数10 9 ≤ x ≤ 10 9和10 9 ≤ y ≤ 10 9
游泳者的位置。
输出
打印两行,都包含整数x和y,10 18 ≤ x,y ≤ 10 18,位置
你和你的同事。
如果有多个有效的解决方案,您可以输出其中任何一个。
问题1:救生员23
样本输入1样本输出1
5
0 0
0 1
1 0
0 -1
-1 0
-3 -1
3 1
样本输入2样本输出2
4
2 4
6 -1
3 5
-1 -1
3 4
3 -1
样本输入3样本输出3
4
5 5
5 -5
-5 5
-5 -5
1 2
-1 2
教练管理范围为:学员离的最近的一个教练
使得教练管理学员数量相同,最多有一个人离两个教练距离相同
代码:(题解)
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>
typedef long long LL;
using namespace std;
int n;
struct node
{
LL x, y;
bool operator <(const node &rhs)const{
return x == rhs.x ? y < rhs.y : x < rhs.x;
}
}a[100005];
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%lld %lld", &a[i].x, &a[i].y);
sort(a + 1, a + 1 + n);
int mid = (n + 2) / 2;
LL MAX = 10000000000LL;
LL x = a[mid].x, y = a[mid].y;
// 必须一上一下 因为如果两个都在下面,那么会使得垂直x轴的直线上的点到两点的距离相同,或者会属于另一边
if(n & 1){
printf("%lld %lld ", x - MAX, y - 1);
printf("%lld %lld ", x + MAX, y + 1);
}else{
printf("%lld %lld ", x - MAX, y - 1);
printf("%lld %lld ", x + MAX, y);
}
return 0;
}
感想:
当时居然还想想当时搜索环形虫那样做,是真的多想了,耽误了很多时间,很大的教训,后来参照题解思路自己又打了一遍,但是输出结果出了些问题。是循环部分条件i没=n;
2020-3-8----3-15补题报告
1.
题目最少拦截系统
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹.
怎么办呢?多搞几套系统呗!你说说倒蛮容易,成本呢?成本是个大问题啊.所以俺就到这里来求救了,请帮助计算一下最少需要多少套拦截系统.
Input输入若干组数据.每组数据包括:导弹总个数(正整数),导弹依此飞来的高度(雷达给出的高度数据是不大于30000的正整数,用空格分隔)
Output对应每组数据输出拦截所有导弹最少要配备多少套这种导弹拦截系统.
耗时 一个小时左右
代码
#include<iostream>/*有参考,题里面有个大坑,是系统可以继续使用*/#include<stdio.h>#include<string.h>#include<math.h>int main(){
int n,i,j,a[30000],m;
int s=1,c;
while(scanf("%d",&n)!=EOF){
for(i=0;i<n;i++)
{
c=0;
scanf("%d",&m);
if(i==0)
a[0]=m;
else
{
for(j=0;j<s;j++)
{
if(a[j]>=m)
{
a[j]=m;
c=1;/*通过c判断*/break;
}
}
if(c==0)
{
a[s]=m;
s++;
}
}
}
printf("%d ",s);
s=1;
}
return 0;
}
感想 中间输入错误,先是while(scanf...)演示错误,改成了scanf,后来答案错误,又改了溢出,最后演示错误,又回到原点了。。。。其实一直都是输入错误,以后要好好读题。。。
2
题目Red and Black
有一个长方形的房间,上面铺着方形瓷砖。每块瓷砖都是红色或黑色的。一个男人站在一块黑色的瓷砖上。从一个瓷砖,他可以移动到四个相邻瓷砖之一。但是他不能在红色瓷砖上移动,他只能在黑色瓷砖上移动。
写一个程序,通过重复上面描述的动作来计算他能到达的黑色瓷砖的数量。
投入
输入由多个数据集组成。数据集以包含两个正整数W和H的一行开始;w和H分别是x和y方向上的图块数量。w和H不超过20。
在数据集中有100多行,每一行都包含100个字符.每个字符代表一个瓷砖的颜色,如下所示。
‘ ‘-黑色瓷砖
#‘ -红色瓷砖
@‘ -黑瓷砖上的人(在数据集中只出现一次)
输出
对于每个数据集,您的程序应该输出一行,其中包含从初始图块(包括其自身)可以到达的图块数量。
耗时 2小时左右
代码 #include <cstdio>/*狼羊那个!*/
#include <iostream>
#include <cstring>/*有参考题解*/
#include<cmath>/*计算他在这个房间里可以到达的黑色瓷砖的数量。*/
using namespace std;
int v[30][30];//在外命名,有点类似于储存数据的容器的作用char map[30][30];
int count,n,m,p,q;
int xy[4][2]={{1,0},{0,1},{-1,0},{0,-1}};/*之前有判断变形虫一个,八个方向数组,跟那个同理*/void f(int x,int y)/*有参考,遍历这里一直出错*/{ int i,j;
for(i=0;i<=3;i++)
{
int xx=x+xy[i][0];
int yy=y+xy[i][1];/*在方向相加上自己一直想不明白*/if(xx>=0&&xx<n&&yy>=0&&yy<m&&v[xx][yy]==0&&map[xx][yy]==‘.‘)//满足条件 递归
{
v[xx][yy]=1;
count++;
f(xx,yy);
}
}
}
int main(){
//freopen("input.txt","r",stdin);int i,j;
while(scanf("%d%d",&m,&n)!=EOF&&m!=0&&n!=0)//注意是输入 列 m 行 n
{
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
cin>>map[i][j];
if(map[i][j]==‘@‘)
{
p=i;
q=j;//@出现对应的坐标
}
v[i][j]=0;//初始化
}
v[p][q]=1;//把当前出现@的位置标记住
count=1;
f(p,q);//从@的位置开始 找".",题解原话遍历查找printf("%d ",count);
}
return 0;
}
/*
题解模板
void dfs()
{
for(所有的邻接节点)
{
if(节点没有被遍历)
{
标记此节点;
dfs(此节点);
}
}
}
*/
感想 搜索遍历类题型还是不理解,之前比赛有过一个类似的题型,结合那个原题认识了一些原理,后来在网上差查询了模板。
3
题目 Climbing Worm
一英寸的虫子在n英寸深的井底。它有足够的能量每分钟爬你英寸,但是在再次爬之前必须休息一分钟。在休息的时候,它会滑落4英寸。攀登和休息的过程然后重复。蠕虫要多久才能爬出井外?我们总是把一分钟的一部分作为一整分钟来计算,如果蠕虫在爬坡结束时刚刚到达井口,我们将假设蠕虫成功了。
投入
将会有多个问题实例。每行将包含3个正整数n,u和d。这些给出了上一段中提到的值。此外,你可以假设d < u,n < 100。n = 0表示输出结束。
输出
每个输入实例应该在一条线上生成一个整数,表示蠕虫爬出井的分钟数。
样本值输入
10 2 1
20 3 1
0 0 0
抽样输出
17
19
耗时
1小时左右
代码 #include<iostream>#include<cstdio>#include<cstring>#include<cmath>using namespace std;
int main(){
int a,b,c;
while(cin>>a>>b>>c)
{
if(a==0)
{
break;
}
int n=0,m=0;
while(1)
{
n=n+b;//没有试第一个样例,其中原本等于17结果输出19,++m改为m++;
m++;
if(n>=a){break;}/*条件漏了*/
n-=c;
m++;
}
cout<<m<<endl;/*忘了回车*/
}
return 0;
}
感想 初用c++,自己测试样例时疏忽了,漏了条件和回车,得加强注意。
4
题目
A == B ?给你两个数字A和B,如果A等于B,你应该写“是”,或者写“否”。
投入
每个测试用例包含两个数字A和b
输出
对于每种情况,如果A等于B,您应该打印“是”,或者打印“否”。
样本值输入
1 2
2 2
3 3
4 3
抽样输出
不
是
是
不
耗时 30分钟左右
代码每个测试用例包含两个数字A和b
输出
对于每种情况,如果A等于B,您应该打印“是”,或者打印“否”。*/#include <cstdio>/*这题该叫a==b plus版*/#include <cstring>/*参考了题解*/#include <iostream>#include<cmath>using namespace std;
void f(char *a){
int n,i;
n=strlen(a)-1;
for(i=n;i>=0;i--)
{
if(a[i]==‘0‘)
{n--;}//判断零位else{ break; }
}
if(a[n]==‘.‘)
n--; //除小数点
a[n+1]=‘ ‘; //加结束标志来去掉*****从博主那里学来的,到时候判长度直接省略
}
int main(){
int i,m,j,k;
char a[100000],b[100000];
while(~scanf("%s%s",a,b))
{
m=strlen(a);
for(i=0;i<m;i++)
{
if(a[i]==‘.‘)
f(a);
}
m=strlen(b);
for(i=0;i<m;i++)
{
if(b[i]==‘.‘)
f(b);
}
if(strcmp(a,b))/*相同则返回一不同则返回0*/printf("NO ");
elseprintf("YES ");
}
return 0;
}
感想 借一位朋友的一句话,我太嫩了,提交多次不过怀疑自己读错题了,后来,真的读错了,参考了题解题意。
5
题目 A hard puzzle
lcy给了feng5166、lwg、jgshining和Ignatius一个难题:给了a和b,如何知道a^b.everybody反对这个BT问题,所以lcy使问题比开始容易。
这个谜题描述的是:给了a和b,如何知道a^b‘s的最后一位数。但是每个人都懒得去解决这个问题,所以他们把智慧汇给你。
投入
有多个测试案例。每个测试用例由两个数字a和b(0<a,b<=2^30组成)
输出
对于每个测试用例,您应该输出a^b‘s最后一位数字。
样本值输入
7 66
8 800
抽样输出
9
6
耗时
40分钟
代码
#include<cstdio>/*有参考*/#include<iostream>#include<cstring>#include<cmath>using namespace std;
int main(){
int s[10][4]={{0},{1},{6,2,4,8},{1,3,9,7},{6,4},{5},{6},{1,7,9,3},{6,8,4,2},{1,9}};/*参考了数据*/int n,m;
int a,b;
while(cin>>a>>b)/*不会判断这里。。。*/
{
m=a%10;
if(m==0||m==1||m==5||m==6)
{n=m;}
else if(m==4||m==9)
{n=s[m][b%2];}
else
{n=s[m][b%4];}
cout <<n<<endl;
}
return 0;
}
感想 有参考题解,起初一直读不懂题意,后来在循环判断上出了错。自己还是接触题型太少,得加强练习。
6
题目
Easier Done Than Said?
密码安全是一件棘手的事情。用户更喜欢简单易记的密码(比如好友),但这种密码通常不安全。一些网站使用随机的计算机生成的密码(比如xvtpzyo),但是用户很难记住它们,有时会把它们写在粘在电脑上的笔记上。一个潜在的解决方案是生成相对安全但仍易于记忆的“可发音”密码。
FnordCom正在开发这样一个密码生成器。你在质量控制部门工作,你的工作是测试生成器并确保密码是可接受的。要被接受,密码必须满足以下三个规则:
它必须包含至少一个元音。
它不能包含三个连续的元音或三个连续的辅音。
它不能包含同一个字母的两个连续出现,除了“ee”或“oo”。
(就这个问题而言,元音是‘a’、‘e’、‘I’、‘o’和‘u’;所有其他字母都是辅音。)请注意,这些规则并不完美;有许多常见的/可发音的单词是不可接受的。
投入
输入由一个或多个潜在的密码组成,每行一个,后跟一行仅包含表示文件结束的单词“end”。每个密码至少有一个最多二十个字母长,并且仅由小写字母组成。
输出
对于每个密码,使用示例中显示的精确格式输出它是否可接受。
样本值输入
a
电视
ptoui
bontres
zoggax
wiinq
eep
豪克图
目标
抽样输出
< a >是可以接受的。
<电视>是不可接受的。
< ptoui >不可接受。
< bontres >不可接受。
< zoggax >不可接受。
< wiinq >不可接受。
< eep >是可以接受的。
<豪克图>是可以接受的。
耗时1小时左右
代码
#include<stdio.h>#include<string.h>#include<math.h>int panduan(char a){ /*检验是否为元音*/if(a==‘a‘||a==‘e‘ ||a==‘i‘||a==‘o‘||a ==‘u‘)
{return 1;}
else {return 0;}
}
int main(){ int i,j,k;
char a[1000],end[]="end";/*有参考*/while(~scanf("%s",a)){
if(strcmp(a,end)==0)break;/*有参考*/int n1=0;
int n2=0;
int t=0;
int c=0;
int n;
n=strlen(a);/*想多了*/for(i=0;i<n;i++){
if(panduan(a[i]))/*判断这里试了很多次一直漏条件*//*有参考*/
{
c=1; /*查连续及字母*/
n1++;
n2=0;
if(n1==2&&a[i]==a[i-1]&&a[i]!=‘e‘&&a[i]!=‘o‘)
{t=1;}
if(n1==3){t=1;}
}
else
{
n2++;
n1=0;
if(n2==2&&a[i]==a[i-1])
{t=1;}
if(n2==3){t=1;}/*判是否连续三次*/
}
if(t!=0){break;}
}
if(t||c==0)printf("<%s> is not acceptable. ",a);
else printf("<%s> is acceptable. ",a);
}
return 0;
}
感想
自己漏了判断条件,该批。。。该想多时不想多,不想多时老想多。。。。
7
题目
Super Jumping! Jumping! Jumping!
如今,一种叫做“超级跳跃!跳跃!跳跃!”在HDU很受欢迎。也许你是个好男孩,对这个游戏知之甚少,所以我现在向你介绍它。
这个游戏可以由两个或两个以上的玩家玩。它由一个棋盘(棋盘)和一些棋子(棋子),所有棋子都用正整数或“开始”或“结束”标记。玩家从起点开始,最后必须跳到终点。在跳跃的过程中,玩家将访问路径中的棋子,但是每个人都必须从一个棋子跳到另一个绝对更大的棋子(你可以假设起点是最小值,终点是最大值)。)。所有玩家都不能后退。一次跳跃可以从一个棋子跳到下一个,也可以跨越多个棋子,甚至你可以直接从起点跳到终点。在这种情况下,你当然会得零分。如果并且只有当一个玩家能够根据他的跳跃解决方案获得更高的分数,他才是赢家。请注意,您的分数来自您跳跃路径中棋子的总价值。
你的任务是根据给定的棋子列表输出最大值。
投入
输入包含多个测试用例。每一个测试用例都被描述成如下一行:
N值_1值_ 2…值_N
保证N不超过1000,并且所有的值I都在32-int的范围内。
从0开始的测试用例终止输入,并且这个测试用例不被处理。
输出
对于每种情况,根据规则打印最大值,一行一种情况。
耗时
1个小时左右
代码
#include<iostream>/*参考的题解思想,结合dp,其实就是最长公共子序列。*/#include<cstdio>/*之前一直不会dp,但这次多少有了一些了解*/#include<cstring>#include<cmath>using namespace std;
int bijiao(int a,int b){
if(a>=b){return a;}
else return b;
}
int main(){
int a[2000],d[2000],n,s=0,M=0,t,i,j;
while(1)
{
cin>>n;
if(n==0){break;}
for(i=0;i<n;i++)
{
cin>>a[i];
d[i]=a[i];/*相当于两数组相等,类似字符串的复制操作,但这是整型数组*/
}
for(i=0;i<n;i++)
{
for(j=0;j<i;j++)
{
if(a[i]>a[j])
{
d[i]=bijiao(d[i],d[j]+a[i]);/*求最大,写的比较最大值函数*/
}
}
M=bijiao(d[i],M);
}
cout<<M<<endl;
M=0;
}
return 0;
}
感想
学习循序渐进,dp现在初步了解了原理。
8
题目
Beat the Spread!
超级碗周日就要到了。为了打发等待中场广告和服装故障的时间,当地黑客组织了一个游戏投注池。会员将赌注压在两个最终分数的总和上,或者压在两个分数的绝对差值上。
给定每种下注的中奖号码,你能推断出最终的分数吗?
投入
输入的第一行包含n,测试用例的数量。接下来是n行,每一行代表一个测试用例。每个测试用例给出s和d,非负整数代表两个最终分数之间的和和(绝对)差。
输出
对于每个测试用例,输出一行给出最后两个分数,最大的第一个。如果没有这样的分数,输出一行包含“不可能”。回想一下,足球得分总是非负整数。
样本值输入
2
40 20
20 40
抽样输出
30 10
不可能的
耗时
1小时左右
代码
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>using namespace std;
int main(){
int n,s,d,t,i;
while(cin>>n)
{
while(n--)
{
cin>>s;
cin>>d;
t=i;
for(i=0;i<s;i++)
{
if(i+i+d==s)
{
cout<<i+d<<" "<<i<<endl;
t=0;
break;
}
}
if(t!=0){cout<<"impossible"<<endl;}
}
}
return 0;
}
感想
转换题意,起初未读懂题意,后来在中间分数计算上也出了很多错误。
9
题目
Specialized Four-Digit Numbers
查找并列出所有十进制记数法中的四位数字,当以十六进制(以16为基数)表示时,这些数字的四位数之和等于其位数之和,当以十二进制(以12为基数)表示时,这些数字也等于其位数之和。
例如,数字2991的(十进制)位数之和为2+9+9+1 = 21。由于2991 = 1*1728 + 8*144 + 9*12 + 3,它的十二进制表示是1893(12),这些数字加起来也是21。但是在十六进制中,2991是BAF16,11+10+15 = 36,所以2991应该被你的程序拒绝。
然而,下一个数字(2992)在所有三种表示(包括BB016)中的总和都是22,所以2992应该在列出的输出中。(我们不希望十进制数少于四位数——不包括前导零——因此2992是第一个正确答案。)
投入
这个问题没有答案。
输出
您的输出是2992和所有满足要求的较大的四位数字(以严格递增的顺序),每一个都在一个单独的行上,没有前导或尾随空格,以一个新行字符结束。输出中不能有空行。输出的前几行如下所示。
样本值输入
这个问题没有答案。
耗时
1小时左右
代码
#include<stdio.h>/*根据体验写三个函数,分别是十二进制、十进制、十六进制*/#include<string>/*最后再判断是否相同即可,因为耗时,判断改成了函数*/#include<math.h>int shi(int a){
int n=0;
while(a>0)
{
n=n+a%10;
a=a/10;
}
return n;
}
int shier(int a){
int n=0;
while(a>0)
{
n=n+a%12;
a=a/12;
}
return n;
}
int shiliu(int a){
int n=0;
while(a>0)
{
n=n+a%16;
a=a/16;
}
return n;
}
int panduan(int a,int b,int c){
if(a==b && b==c)
{return 1;}
else
{return 0;}
}
int main(){
int i;
for(i=2992;i<10000;i++)
{
int a;
int b;
int c;
a=shi(i);
b=shier(i);
c=shiliu(i);
int t;
t=panduan(a,b,c);
if(t)
{
printf("%d ",i);
}
}
return 0;
}
感想
我还在想能不能直接输出答案。。。。后来不能过,于是按原本方式好好写了代码,其实只是几个函数就可以判断了,这次想取巧....不过看样子不行。
1*题目当寒月还在读大一的时候,他在一本武林秘籍中(据后来考证,估计是计算机基础,狂汗-ing),发现了神奇的二进制数。
如果一个正整数m表示成二进制,它的位数为n(不包含前导0),寒月称它为一个n二进制数。所有的n二进制数中,1的总个数被称为n对应的月之数。
例如,3二进制数总共有4个,分别是4(100)、5(101)、6(110)、7(111),他们中1的个数一共是1+2+2+3=8,所以3对应的月之数就是8。
Input给你一个整数T,表示输入数据的组数,接下来有T行,每行包含一个正整数 n(1<=n<=20)。
Output对于每个n ,在一行内输出n对应的月之数。
Sample Input3
1
2
3Sample Output1
3
8
耗时
40分钟左右
代码
#include <stdio.h>#include <math.h>int main(){
int T,m,i,j;
int a[1000];
a[1]=1;
a[2]=3;
for(i=3;i<21;i++)
{
a[i]=pow(2,i-2)+2*a[i-1];/*参考递推公式为f(m)=2^(m-2)+2*f(m-1)*/
}
scanf("%d",&T);
while(T--)
{
scanf("%d",&m);
printf("%d ",a[m]);
}
return 0;
}
感想:自己用了暴力的笨方法,但是输出一直出问题,网上参考了递推公式后结果正确。感觉自己思维性锻炼还不足;
2 题目A Mathematical Curiosity
给定两个整数n和m,计算整数对(a,b)的数量,使0 < a < b < n ,( a^2+b^2+m)/(ab)为整数。
这个问题包含多个测试用例!
多重输入的第一行是一个整数N,然后是一个空行,其后是N个输入块。每个输入块都采用问题描述中指示的格式。输入块之间有一个空行。
输出格式由N个输出块组成。输出块之间有一个空行。
投入
您将在输入中获得一些案例。每种情况都由包含整数n和m的一行指定。输入的结束由n = m = 0的情况指示。您可以假设0 < n <= 100。
输出
对于每个案例,打印案例编号以及满足给定属性的对(a,b)的数量。按照如下所示的格式,在一行中打印每种情况的输出。
耗时
50分钟左右
代码
#include<stdio.h>int panduan(int a,int b)/*这里忘了打int*/{
int i,j,t=0;
for(i=1;i<a;i++)
{
for(j=i+1;j<a;j++)
{
if((i*i+j*j+b)%(i*j)==0)
t++;
}
}
return t;
}
int main(){
int N;
scanf("%d ",&N);
while(N--)
{
int n,m;
int d=0;
int c=0;
while(scanf("%d %d",&n,&m)!=EOF)
{
if (n==0&&m==0){break;}
else
{
/*c的作用范围也出了错*/
d=panduan(n,m);
printf("Case %d: %d ",++c,d);
}
}
if(N)/*没好好看题忘了空行,N只有一的情况,输入块之间有一个空行。*/printf(" ");
}
return 0;}
感想 又是读题错误,还有作用范围,错误很低级,要好好抓细节
10 题目:
C语言合法标识符
输入一个字符串,判断其是否是C的合法标识符。
Input输入数据包含多个测试实例,数据的第一行是一个整数n,表示测试实例的个数,然后是n行输入数据,每行是一个长度不超过50的字符串。
Output对于每组输入数据,输出一行。如果输入数据是C的合法标识符,则输出"yes",否则,输出“no”。
Sample Input3
12ajf
fi8x_a
ff ai_2Sample Outputno
yes
no
耗时
1个小时左右
代码
#include<stdio.h>int panduan(char a[]){
int i=1;
if(!(a[0]>=‘A‘&&a[0]<=‘Z‘||a[0]>=‘a‘&&a[0]<=‘z‘||a[0]==‘_‘))
return 0;
while(a[i]!=‘ ‘)
{
if(!(a[i]>=‘A‘&&a[i]<=‘Z‘||a[i]>=‘a‘&&a[i]<=‘z‘||a[i]==‘_‘||a[i]>=‘0‘&&a[i]<=‘9‘))
return 0;
i++;
}
return 1;
}
int main()/*有参考题解*/{
int n,i;
char a[100],c;
scanf("%d %c",&n,&c);
for(i=0;i<n;i++)
{
gets(a);/*注意区分scanf和gets*/if(panduan(a))/*区分EOF与直接判断*/printf("yes ");
elseprintf("no ");
/*输出想多了*/
} return 0;
}
感想
EOF判断上出了错误,因为担心字符串打了getchar,但还是自己想多了,函数那里有参考。初期自己打了几个样例,但是判断不出来。
11 题目 18岁生日
Gardon的18岁生日就要到了,他当然很开心,可是他突然想到一个问题,是不是每个人从出生开始,到达18岁生日时所经过的天数都是一样的呢?似乎并不全都是这样,所以他想请你帮忙计算一下他和他的几个朋友从出生到达18岁生日所经过的总天数,让他好来比较一下。
Input一个数T,后面T行每行有一个日期,格式是YYYY-MM-DD。如我的生日是1988-03-07。
OutputT行,每行一个数,表示此人从出生到18岁生日所经过的天数。如果这个人没有18岁生日,就输出-1。
Sample Input1
1988-03-07Sample Output6574
耗时
2小时左右(其实打了很多次)
代码
#include <stdio.h>/*题解参考,自己天数,后台测试杀我*/int panduan(int year){
if((year%4==0 && year%100!=0)||year%400==0)
return 1;
else return 0;}
int main(){
int N,i,year,month,day;
int num;
scanf("%d",&N);
while(N--)
{
scanf("%d-%d-%d",&year,&month,&day);
//输入生日的年,月,日if( month==2 && day==29) printf("-1 ");
//2月29日出生,则输出-1else
{
num=0;
if(month>=3) //月份大于2,并且该年后一年的平或润 决定过一岁度过的天数
{
for(i=year+1; i<=year+18; i++)
{
if(panduan(i)) {num+=366;}
else {num+=365;}
}
}
else if(month<=2)
//月份小于等于2,该年的平或润 决定过一岁度过的天数
{
for(i=year; i<=year+17; i++)
{
if(panduan(i)) {num+=366;}
else {num+=365;}
}
}
printf("%d ",num);
}
} return 0;}
/*
#include<stdio.h>
#include<math.h>
int panduan(int y)
{
if(((y%4==0&&y%100!=0)||y%400==0)) {return 1;}
else{return 0;}
}
int main()
{
int n,y,m,d,i,j,sum=0;
scanf("%d",&n);
while(n--)
{
scanf("%d-%d-%d",&y,&m,&d);
if(panduan(y)!=0&&m==2&&d==29)
{
printf("-1 ");
}
else
{
sum=365*18;
for(i=0;i<18;i++)
{
if(panduan(y+i)){sum++;}
}
if(panduan(y))
{if(m==1)
{
sum++;
}
else if(m==2&&d<=28)
{sum++;}
}
if(panduan(y+18)==1)
{
if(y>2) {sum++;}
}
printf("%d ",sum); }
}
return 0;}
*//*附上自己出错的代码*/
感想:一直找不到错误,后来参考了题解,发现细节出错,对个别特殊情况判断有问题。
12 题目:
Reverse Number
欢迎参加2006年4月计算机学院编程大赛!
特别地,我向所有的新生问好!你是HDU ACM的未来!现在,我必须告诉你ACM的问题总是不容易,但是,除了这个...哈哈!
给你一个整数;你的任务是输出它的反码。这里,反向数定义如下:
1.以零结尾的正整数的倒数是一般的倒数,例如,倒数(12)= 21;
2.负整数的倒数是负数,例如,倒数(-12)=-21;
3.以0结尾的整数的倒数被描述为例子,倒数(1200) = 2100。
投入
输入文件包含多个测试用例。第一行有一个正整数n (n<100),这意味着测试用例的数量,然后是n个32位整数。
输出
对于每个测试用例,您应该输出它的反向数,每行一个用例。
样本值输入
3
12
-12岁
1200
抽样输出
21
-21岁
2100
耗时:2小时
代码:
#include <stdio.h>/*有参考*/
#include <string.h>/*还是反码补码的原理,但是翻转一直出错*/
#define N 100
int main(void){
int t, n, m;
char s[N], c;
while(scanf("%d", &t)!=EOF)
{while(t--)
{
scanf("%s", s);
n = 0;
m = strlen(s) - 1;
if(s[n] == ‘-‘)/*负号判断*/
{n++;}
while(m >= 0 && s[m] == ‘0‘)
{m--;}
while(n < m)
{
c = s[n];
s[n] = s[m];
s[m] = c;
n++;
m--;
}
感想:在倒换时出错多次,自测结果一直输入不对。后来再做题发现G++能过。。。。
13题目Ignatius‘s puzzle
伊格内修斯数学不好,他遇到了一道难题,所以他别无选择,只能求助于艾迪。这个问题描述了that:f(x)=5*x^13+13*x^5+k*a*x,input的一个非负整数k(k<10000),要找到最小非负整数a,就要使任意整数x,65|f(x)如果
不存在a,则打印“否”。
投入
输入包含几个测试用例。每个测试用例都由一个非负整数k组成,更多细节见样本输入。
输出
输出包含一个字符串“否”,如果您找不到,或者您应该输出一个包含a的行。更多详细信息请参见示例输出。
样本值输入
11
100
9999
抽样输出
22
不
43
耗时
1.0小时左右
代码
#include<stdio.h>int main()/*要找到最小非负整数a,就要使任意整数x,65|f(x)如果*/{/*有参考*/long long a,n;
while(scanf("%lld",&n)!=EOF)
{
a=0;
for(a=0;a<=65;a++)
{
if((18+n*a)%65==0)/*由题目得,公式,主要f(x)可以被65整除*/
{
printf("%lld ",a);
break;
}
}
if(a>65)
{printf("no ");}
}
return 0;
}
感想
花了很多时间去想算法,主要是f(X)被65整除,参考了题解,自己打时把int换成了long long 因为溢出经常不明,有了以前的经验现在对使用int很谨慎。
14 题目
分拆素数和
把一个偶数拆成两个不同素数的和,有几种拆法呢?
Input输入包含一些正的偶数,其值不会超过10000,个数不会超过500,若遇0,则结束。Output对应每个偶数,输出其拆成不同素数的个数,每个结果占一行。Sample Input30
26
0Sample Output3
2
耗时
40分钟左右
代码
#include<stdio.h>#include<math.h>int jisuan(int k,int *a){
int sum=0;
int i,j;
for(i=1;a[i]<k;i++)/*a[j]<k,a[i]<k*//*这里有参考*/
{
for(j=i+1;a[j]<k;j++)
{
if(a[i]+a[j]==k)
sum=sum+1;
}
}
return sum;
}
nt main(){
int a[10000];
int i,j,t,c=1;
for(i=2;i<10000;i++)/*参考*/
{
t=1;
for(j=2;j<i;j++)
{
if(i%j==0)
{
t=0;
break;
}
}
if(t!=0) {a[c++]=i;}
}
int k,sum;
while(~scanf("%d",&k)&&k!=0)
{
sum=jisuan(k,a);
printf("%d ",sum);
}
return 0;
}
感想/*#include<stdio.h>int main(){
int a[10000],n,i,j,m;
for(i=3;i<=10000;i++)
{
a[i]=i; }
for(i=2;i<=10000;i++)
{ for(j=2*i;j<=10000;j+=i)
{ a[j]=0;}}
while(scanf("%d",&n)!=EOF&&n)
{ m=0;
for(i=3;2*i<n;i++)
if(a[i]+a[n-i]==n)
++m;
printf("%d ",m);
}}*/四个月之前的旧题,没有过,后来自己又调了几次,结果越调越不对,后来网上参考了其他算法,觉得自己之前想的太简单了,归结于读题不准。
15 题目:u Calculate e
e的一个简单数学公式是
其中n被允许去无穷大。使用相对较小的n值,这实际上可以产生非常精确的e近似值。
输出
对于从0到9的n值,输出由上述公式生成的e的近似值。您的输出的开始应该如下所示。
抽样输出
n e
- -
0 1
1 2
2 2.5
3 2.66666667
4 2.70833333
耗时:1.0小时左右
感想:
/*#include<stdio.h>
int main(void)查到了打表
{
printf("n e - ----------- 0 1 ");
printf("1 2 2 2.5 3 2.666666667 4 2.708333333 ");
printf("5 2.716666667 6 2.718055556 7 2.718253968 ");
printf("8 2.718278770 9 2.718281526 ");
return 0;发现这题居然直接输出也可以,就是结果要好好算
}
*/
#include<stdio.h>int main(){
int i;
double n, sum = 1.0, temp = 1.0;
printf("n e - ----------- 0 1 1 2 2 2.5 ");
for (i = 1; i <= 9; i++) {
temp *= (double)i;/*在这里强制类型转换了保证小数点*/
sum += 1.0 / temp;
if (i>2)
printf("%d %.9f ", i, sum);/*自己打时总是保留位数出错,答这道题时想起来int四舍五入之前有用过+0.5的操作,虽然本题没用到*/
}
return 0;
}
16 题目
统计元音
统计每个元音字母在字符串中出现的次数。
Input输入数据首先包括一个整数n,表示测试实例的个数,然后是n行长度不超过100的字符串。
Output对于每个测试实例输出5行,格式如下:
a:num1
e:num2
i:num3
o:num4
u:num5
多个测试实例之间由一个空行隔开。
请特别注意:最后一块输出后面没有空行:)
Sample Input2
aeiou
my name is ignatiusSample Outputa:1
e:1
i:1
o:1
u:1
a:2
e:1
i:3
o:0
u:1
耗时
1.0小时左右
代码
#include<stdio.h>#include<string.h>int main(){
int n,i,j,m;
char s[100];
scanf("%d",&n);
getchar();
for(j=0;j<n;j++)
{
int a1=0,e1=0,i1=0,o1=0,u1=0;
gets(s);
m=strlen(s);
for(i=0;i<m;i++)
{
if(s[i]==‘a‘)a1++;
else if(s[i]==‘e‘)e1++;
else if(s[i]==‘i‘)i1++;
else if(s[i]==‘o‘)o1++;
else if(s[i]==‘u‘)u1++;
}
printf("a:%d ",a1);
printf("e:%d ",e1);
printf("i:%d ",i1);
printf("o:%d ",o1);
printf("u:%d ",u1);
if(j<n-1)printf(" ");/*参考题解,之前一直卡在输出格式上了*/
}
return 0;
}
感想 又是被卡输出格式的一题,想起来当初在计蒜客被卡的经历;刚开始wa一直以为是自己结果错误,一直调...居然没想到是格式。
17 题目
Octorber 21st
10月21日,HDU 50岁生日就要到了。多么激动人心的一天!!作为HDU的学生,我总是想知道从今天到10月21日有多少天。所以,写一个问题并告诉我答案。当然,我给你的日期总是在2006年。
投入
输入由测试用例组成。输入文件的第一行给出了T的个数。在代表日期的T行之后,每行一个日期。日期的格式是“月日”,其中月是1(表示1月)到12(表示12月)之间的数字,日是1到31之间的数字。输入中的所有日期都是2006年,您可以假设输入中的所有日期都是合法的(合法)。
输出
对于每种情况,如果日期在10月21日之前,您应该打印一个介于该日期和10月21日之间的数字。如果这一天已经过了10月21日,就写下“真遗憾,已经过去了!”。如果日期是10月21日,打印“今天!!”。
样本值输入
7
10 20
10 19
10 1
10 21
9 1
11 11
12 12
抽样输出
1
2
20
就是今天!!
50
真遗憾,已经过去了!
真遗憾,已经过去了!
耗时 40小时左右
代码#include<stdio.h>#include<string.h>#include<math.h>/*起初未读懂题,后来是自己想复杂了*/int main()/*其实跟之前计算天数差不多*/{
int day[10]={0,31,28,31,30,31,30,31,31,30};
int n,m,d,i;
scanf("%d",&n);
while(n--)
{
int num;
num=0;
scanf("%d %d",&m,&d);
if(m==10&&d==21){printf("It‘s today!! ");}/*按题意判断*/else if(m>10||(m==10&&d>21))/*按题意判断*/
{
printf("What a pity, it has passed! ");
}
else if(m==10&&d<21)/*按题意判断*/
{
printf("%d ",21-d);
}
else if(m<10)/*按题意判断,特殊*/
{
for(i=m;i<=8;i++)/*这里循环期间出了问题,因为循环溢出了9.1结果一直出不来*/
{
num=num+day[i];
}
num=num+day[9];
num=num-d;
num=num+21;
printf("%d ",num);
}
}
return 0;
}
感想 曾经5个月前,我对这题望而却步,现在发现我会了但是我想的过多了,最后的循环条件出了错,题意很好理解,但是要看是否每个条件都顾虑到,记得自己还因为while(scanf(“%d")!=EOF)出错,其实每次直接scanf就行不用while
18 题目
首字母变大写
输入一个英文句子,将每个单词的第一个字母改成大写字母。
Input输入数据包含多个测试实例,每个测试实例是一个长度不超过100的英文句子,占一行。
Output请输出按照要求改写后的英文句子。
Sample Inputi like acm
i want to get an acceptedSample OutputI Like Acm
I Want To Get An Accepted
耗时
2小时左右
代码
#include<stdio.h>#include<string.h>#include<math.h>int main(){
char s[200];
int i,n;
while(gets(s))
{
n=strlen(s);
if(s[0]>=‘a‘&&s[0]<=‘z‘)/*第一个*/
s[0]=s[0]-32;
for(i=0;i<n;i++)
{
if(s[i]>=‘a‘&&s[i]<=‘z‘&&s[i-1]==‘ ‘)/*判断空格*/
s[i]=s[i]-32;
printf("%c",s[i]);
}
printf(" ");
}
return 0;
}
感想
中间把第一个和后面的字母分开了,起初还在考虑防溢出,其实直接判断空格就可以
19 题目
不容易系列之一
大家常常感慨,要做好一件事情真的不容易,确实,失败比成功容易多了!
做好“一件”事情尚且不易,若想永远成功而总从不失败,那更是难上加难了,就像花钱总是比挣钱容易的道理一样。
话虽这样说,我还是要告诉大家,要想失败到一定程度也是不容易的。比如,我高中的时候,就有一个神奇的女生,在英语考试的时候,竟然把40个单项选择题全部做错了!大家都学过概率论,应该知道出现这种情况的概率,所以至今我都觉得这是一件神奇的事情。如果套用一句经典的评语,我们可以这样总结:一个人做错一道选择题并不难,难的是全部做错,一个不对。
不幸的是,这种小概率事件又发生了,而且就在我们身边:
事情是这样的——HDU有个网名叫做8006的男性同学,结交网友无数,最近该同学玩起了浪漫,同时给n个网友每人写了一封信,这都没什么,要命的是,他竟然把所有的信都装错了信封!注意了,是全部装错哟!
现在的问题是:请大家帮可怜的8006同学计算一下,一共有多少种可能的错误方式呢?
Input输入数据包含多个多个测试实例,每个测试实例占用一行,每行包含一个正整数n(1<n<=20),n表示8006的网友的人数。Output对于每行输入请输出可能的错误方式的数量,每个实例的输出占用一行。Sample Input2
3Sample Output1
2
耗时
1.0小时左右
代码
#include<stdio.h>/*查的错排公式的模板*/int main(){
int n,m,i,k;
long long a[21];/*注意防溢出*/
a[1]=0;
a[2]=1;
for(i=3;i<=20;i++)
{
a[i]=(i-1)*(a[i-1]+a[i-2]);/*一直类推找规律*/
}
while(scanf("%d",&n)!=EOF)
{
printf("%lld ",a[n]);
}
return 0;
}
/*当n个编号元素放在n个编号位置,元素编号与位置编号各不对应的方法数用D(n)表示,那么D(n-1)就表示n-1个编号元素放在n-1个编号位置,各不对应的方法数,其它类推.
第一步,把第n个元素放在一个位置,比如位置k,一共有n-1种方法;
第二步,放编号为k的元素,这时有两种情况:⑴把它放到位置n,那么,对于剩下的n-1个元素,由于第k个元素放到了位置n,剩下n-2个元素就有D(n-2)种方法;⑵第k个元素不把它放到位置n,这时,对于这n-1个元素,有D(n-1)种方法。
综上得到:
D(n) = (n-1) [D(n-2) + D(n-1)]
特殊地,D(1) = 0, D(2) = 1。*/
感想
起初也是递归运算,但是结果一直出错,经常重复,后来查了错排公式的模板,期间用long long防溢出,记到了错题类型里面,错排公式新学到了。
题目
20 Optimal Parking
停车场问题
耗时1.0小时左右
代码
#include<stdio.h>int main()/*读题,其实是(最大值-最小值*2,自己把问题复杂化了*/{
int N,c,n,i,t;
scanf("%d",&N);
while(N--)
{
scanf("%d",&n);
int max=0;
int min=100;/*注意*/for(i=0;i<n;i++)
{
scanf("%d",&t);
if(t>max){max=t;}
if(t<min){min=t;}
}
printf("%d ",(max-min)*2);
}
return 0;
}
感想
题目虽然看着难其实多想想就可以了,绝对不能自己吓自己。
21 题目
Dragons
基里托被卡在了他现在玩的MMORPG的水平上。为了在游戏中继续前进,他必须打败住在这个等级的所有n条龙。基里托和龙有力量,用一个整数表示。在两个对手的决斗中,决斗的结果取决于他们的实力。最初,基里托的力量等于s
如果基里托开始与第一条(1 ≤ i ≤ n)龙决斗,并且基里托的力量不大于龙的力量xi,那么基里托将输掉决斗并死去。但是如果基里托的力量大于龙的力量,那么他将击败龙,并获得一个由伊增加的额外力量。
基里托可以以任何顺序与龙战斗。决定他是否能进入游戏的下一个阶段,也就是说,击败所有的龙而没有一点损失。
投入
第一行包含两个用空格分隔的整数s和n (1 ≤ s ≤ 104,1 ≤ n ≤ 103).接下来是n行:第I行包含空格分隔的整数xi和易(1 ≤ xi ≤ 104,0 ≤ yi ≤ 104)——第I行龙的力量和击败它的奖励。
输出
如果基里托不能前进到下一级,在一行打印“是”(不带引号),如果不能,则打印“否”(不带引号)。
耗时
1.0小时左右
代码
#include<stdio.h>#include<math.h>#include<string.h>struct dragon
{
long long dengji;
long long jiangli;
}a[1000];
int main(){
long long s,n,i,t,c,j;
while(scanf("%lld %lld",&s,&n)!=EOF)
{
if(n==0){break;}
for(i=0;i<n;i++)
{
scanf("%lld %lld",&a[i].dengji,&a[i].jiangli);
}
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(a[i].dengji>a[j].dengji)
{
t=a[i].dengji;
a[i].dengji=a[j].dengji;
a[j].dengji=t;
c=a[i].jiangli;
a[i].jiangli=a[j].jiangli;
a[j].jiangli=c;
}
}
}
for(i=0;i<n;i++)
{
if(s>a[i].dengji) {s=s+a[i].jiangli;}
else{t=-1;break;}
}
if(t==-1){printf("NO ");}
else{printf("YES ");}
}
return 0;
}
感想
自己的代码实属暴力。。。耗时挺多的也繁琐,别人也说挺难读的,对优化代码的能力需要提高
22题目Even Subset Sum Problem
给你一个数组
a
包括
n
正整数。找到其元素的非空子集,使它们的和是偶数(即可被除尽
2
)或确定不存在这样的子集。
给定数组和所需子集可以包含相等的值。
投入
第一行包含一个整数
t1≤t≤100),要解决的测试用例数。描述
t
测试用例随之而来。
每个测试用例的描述由两行组成。第一行包含一个整数
n1≤n≤100
),数组长度
第二行包含n个整数
a1,a2,…,an(1≤ai≤100元素
给定的数组
可以包含相等的值(重复值)。
输出
对于每个测试用例输出1
如果没有这样的元素子集。否则输出正整数k,所需子集中的元素数。然后输出
k个不同的整数(1≤pi≤n),所选元素的索引。如果有多个解决方案,输出其中任何一个。
耗时
40分钟左右
代码
#include<stdio.h>#include<math.h>int main(){
int N;
scanf("%d",&N);
while(N--)
{
int n;
scanf("%d",&n);
int a[n],i,j;
int t1=-1,c=0,a1,a2;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
int b[2];
for(i=0;i<n;i++)
{
if(a[i]%2==0)
{
t1=1;
printf("1 %d ",i+1);
break;
}
else
{b[c]=1+i;
c++;
if(c==2)
{t1=1;
printf("2 %d %d ",b[0],b[1]);
break;
}
}
}
if(t1==-1){printf("-1 ");}
c=0;
}
return 0;
}
感想
打下来较为顺畅,按题意打即可,平时常出错的点多注意就可;
以上是关于2020-3-14 acm训练联盟周赛Preliminaries for Benelux Algorithm Programming Contest 2019 解题报告+补题报告的主要内容,如果未能解决你的问题,请参考以下文章
[ICPC训练联盟周赛1] CTU Open Contest 2019
UCF Local Programming Contest 2017训练联盟周赛
2020.3.28-ICPC训练联盟周赛,选用试题:UCF Local Programming Contest 2016
03.28,周六,12:00-17:00,ICPC训练联盟周赛,选用试题:UCF Local Programming Contest 2016正式赛。