概述
ICPC训练联盟2021寒假冬令营 直播课
- Day 1
- A Specialized Four-Digit Numbers
- B Pia-Latin
- C Tic Tac Toe
- D Factorial! You Must be Kidding!!!
- E Function Run Fun
- Day 2
- A Maya Calendar
- B Diplomatic License
- C Accordian Patience
- D Broken Keyboard
- E Satellites
- F Fourth Point!!
- G The Circumference of the Circle
- H Titanic
- Day 3
Day 1
注:未添加问题描述。仅供个人学习参考。
A Specialized Four-Digit Numbers
问题描述:
(1)找到并列出所有具有这样特性的十进制的4位数字:
其4位数字的和等于这个数字以16进制表示时的4位数字的和,也等于这个数字以12进制表示时的4位数字的和。
(2)例如,整数2991的(十进制)4位数字之和是 2+9+9+1 = 21,
因为 2991 = 11728 + 8144 + 9*12 + 3,所以其12进制表示为189312,4位数字之和也是21。
但是2991的十六进制表示为BAF16,并且11+10+15 = 36,因此2991被程序排除了。
下一个数是2992,3种表示的各位数字之和都是22 (包括BB016),因此2992要被列在输出中。
(本题不考虑少于4位数字的十进制数----排除了前导零----因此2992是第一个正确答案。)
输入:
本题没有输入。
输出:
输出为2992和所有比2922大的满足需求的4位数字(以严格的递增序列),
每个数字一行,数字前后不加空格,以行结束符结束。
输出没有空行。输出的前几行如下所示。
#include <iostream>
using namespace std;
int Calc(int base,int n) //计算和返回n转换成base进制后的各位数字之和
{
int sum=0;
for(;n;n/=base)
sum+=n%base;
return sum;
}
int main()
{
int i,a;
for(i=2992;i<9999;i++) //枚举[2992..9999]内的每个数i
{
a=Calc(10,i);
if(a==Calc(12,i) && a==Calc(16,i))
cout<<i<<endl;
}
return 0;
}
B Pia-Latin
问题描述:
(1)您意识到PGP加密系统还不足够保护您的电子邮件,所以,
你决定在使用PGP加密系统之前,先把您的明文字母转换成Pig Latin(一种隐语),以完善加密。
(2)每行文本将包含一个或多个单词。一个“单词”被定义为一个连续的字母序列(大写字母和/或小写字母)。
(3)单词根据以下的规则转换为Pig Latin,非单词的字符在输出时则和输入中出现的完全一样:
[1] 以元音字母(a、e、i、o或u,以及这些字母的大写形式)开头的单词,
要在其后面附加字符串“ay”(不包括双引号)。
例如,“apple”变成“appleay”。
[2] 以辅音字母(不是A, a, E, e, I, i, O, o, U 或 u的任何字母)开头的单词,
要去掉第一个辅音字母,并将之附加在单词的末尾,然后再在单词的末尾加上“ay”。
例如,“hello”变成“ellohay”。
[3] 不要改变任何字母的大小写。
输入和输出:
请您编写一个程序,输入任意数量行的文本,并以Pig Latin输出。
#include <iostream>
using namespace std;
char temp[1000005]; //输入的文本
int isab(char c) //是否是字母
{
if(c>='a' && c<='z')
return 1;
if(c>='A' && c<='Z')
return 1;
return 0;
}
int vowel(char c) //是否是元音字母
{
if(c=='a' || c=='e' || c=='i' || c=='o' || c=='u')
return 1;
if(c=='A' || c=='E' || c=='I' || c=='O' || c=='U')
return 1;
return 0;
}
int main()
{
while(gets(temp)){
int s=0,t=0;
while(temp[s])
if(!isab(temp[s])){ //不是字母
printf("%c",temp[s++]);
t=s;
}
else if(isab(temp[t])) //是字母
t++;
else{
if(!vowel(temp[s])){ //辅音字母开头
for(int i=s+1;i<t;++i)
printf("%c",temp[i]);
printf("%c",temp[s]);
}
else
for(int i=s;i<t;++i)
printf("%c",temp[i]);
printf("ay");
s=t;
}
printf("n");
}
return 0;
}
C Tic Tac Toe
#include <stdio.h>
char plant[4][4];
int i,j;
int win(char c) //判断是否赢
{
for(i=0;i<3;i++)
{
for(j=0;j<3 && plant[i][j]==c; j++)
if(j==2) return 1;
for(j=0;j<3 && plant[j][i]==c; j++)
if(j==2) return 1;
}
for(i=0;i<3 && plant[i][i]==c;i++)
if(i==2) return 1;
for(i=0;i<3 && plant[i][2-i]==c;i++)
if(i==2) return 1;
return 0;
}
int main()
{
int flag;
int n,xcount,ocount;
while(scanf("%d",&n)!=EOF)
{
getchar();
while(n--)
{
xcount=0;
ocount=0;
for(i=0;i<3;i++)
scanf("%s",plant[i]);
flag=1;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
if(plant[i][j]=='X')
xcount++;
else if(plant[i][j]=='O')
ocount++;
}
if(win('X') && win('O'))
flag=0;
if(win('X')&& xcount==ocount)
flag=0;
if(ocount>xcount || xcount-ocount>1)
flag=0;
if(win('O') && ocount!=xcount)
flag=0;
if(win('X') && ocount==xcount)
flag=0;
if(flag)
printf("yesn");
else
printf("non");
}
}
return 0;
}
D Factorial! You Must be Kidding!!!
问题描述:
Arif在Bongobazar买了台超级电脑。Bongobazar是达卡(Dhaka)的二手货市场,因此他买的这台超级电脑也是二手货,存在一些问题。
其中一个问题是这台电脑的C/C++编译器的无符号长整数的范围已经被改变了。现在新的下限是10000,上限是6227020800.Arif用C/C++写了一个程序,确定一个整数的阶乘。
整数的结成递归定义为:
Factorial(0)=1;
Factorial(n)=nFactorial(n-1)
当然,可以改变这样的表达式,例如,可以写成:
Factorial(n)=n(n-1)*Factorial(n-2)
这一定义也可以转换为迭代的形式。
但Arif知道,在这台超级电脑上,这一程序不可能正确地运行。
请您编写一个程序,模拟在正常的计算机上的改变行为。
输入和输出:
(1)输入包含若干行,每行给出一个整数n。不会有整数超过6位。输入以EOF结束。
(2)对于每一行的输入,输出一行。
如果n!的值在Arif 计算机的无符号长整数范围内,输出行给出n!的值;
否则输出行给出如下两行之一:
Overflow! //(当 n! > 6227020800)
Underflow! //(当 n! < 10000)
#include <iostream>
using namespace std;
const long long FACT1=10000,FACT2=6227020800; //下限和上限
const int N=13;
long long F[N+1];
void init() //离线计算F[i]=i!, 0<i<13.
{
F[0]=1;
for(int i=1;i<=N;i++)
F[i]=i*F[i-1];
}
int main()
{
init();
int n;
while(~scanf("%d",&n))
if(n>N || (n<0 && (-n)%2==1))
printf("Overflow!n");
else if(F[n]<FACT1 || (n<0 && (-n)%2==0))
printf("Underflow!n");
else
printf("%lldn",F[n]);
return 0;
}
E Function Run Fun
#include <stdio.h>
#include <string.h>
#define N 20
int f[N+1][N+1][N+1]; //三维的数组f[a][b][c]用于记忆w(a,b,c)
int w(int a,int b,int c) //根据递归定义给出递归函数w
{
if(a<=0 || b<=0 || c<=0) return 1;
else if(a>N || b>N || c>N) return w(N,N,N);
else if(f[a][b][c]) return f[a][b][c]; //f[a][b][c]已经记忆w(a,b,c)
else if(a<b && b<c) return f[a][b][c]=w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
else return f[a][b][c]=w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
}
int main(void)
{
memset(f,0,sizeof(f)); //三维的数组f初始化赋值0
int a,b,c;
while(scanf("%d%d%d",&a,&b,&c)!=EOF){ //每次循环处理一个整数三元组
if(a==-1 && b==-1 && c==-1) return 0;
printf("w(%d,%d,%d)=%dn",a,b,c,w(a,b,c));
}
return 0;
}
Day 2
A Maya Calendar
#include <iostream>
#include <string>
using namespace std;
string haab[19]={"pop","no","zip","zotz","tzec","xul","yoxkin","mol","chen","yax","zac","ceh","mac","kankin","muan","pax","koyab","cumhu","uayet"}; //Haab历
string tzolkin[20]={"imix","ik","akbal","kan","chicchan","cimi","manik","lamat","muluk","ok","chuen","eb","ben","ix","mem","cib","caban","eznab","canac","ahau"}; // Tzolkin历
struct data
{
int date;
string month;
int year;
}; //表示日期的结构体
void convert(data &x) //
{
long current;
int i;
for(i=0;i<20;++i) //当前月份是Haab历的哪个月
if(x.month==haab[i]) break;
current=x.year*365+i*20+x.date+1; //这一日期从世界开始记起的天数
int num,year=0; //num为输出中的数字,year为输出中的年份
string word;
if(current%13==0)
num=13;
else
num=current%13;
while((current-260)>0) //Tzolkin历一年260天
{
++year;
current-=260;
}
if(current==0)
word="ahau"; //表示前一年的最后一天
else
{
while((current-20>0))
current-=20;
if(current==0)
word="ahau"; //表示前一个月的最后一天
else
word=tzolkin[current-1];
}
cout<<num<<" "<<word<<" "<<year<<endl;
}
int main()
{
int i,n;
char ch; //用于存储输入中的点'.'
cin>>n;
data *p=new data[n];
for(i=0;i<n;++i)
cin>>p[i].date>>ch>>p[i].month>>p[i].year; //输入Haab历日期
cout<<n<<endl;
for(i=0;i<n;++i)
convert(p[i]);
return 0;
}
B Diplomatic License
#include <iostream>
using namespace std;
struct Point
{
long long x,y;
}first,last,now; //x和y坐标的结构体表示
int n; //n个国家
int main()
{
while(scanf("%d",&n)!=EOF) //每次循环处理一个测试用例
{
printf("%d ",n);
scanf("%lld %lld ",&first.x,&first.y); //起点的坐标
now=first;
for(int i=1;i<n;i++) //使用中点坐标公式
{
scanf("%lld%lld",&last.x,&last.y);
printf("%.6f %.6f ",(last.x+now.x)/2.0,(now.y+last.y)/2.0);
now=last;
}
printf("%.6f %.6f ",(last.x+first.x)/2.0,(last.y+first.y)/2.0);
putchar('n');
}
return 0;
}
C Accordian Patience
#include <stdio.h>
struct Node
{
int size; //为牌顶时的牌的张数
Node *pre,*post; //前后指针
Node *down; //牌堆下一张牌的指针
char a,b; //面值和花色
Node():pre(NULL),post(NULL),down(NULL),size(1){}
};
inline void insertNode(Node *&m,Node *&n) //节点n替代节点m
{
n->post=m->post;
n->pre=m->pre;
if(m->post) m->post->pre=n; //如果节点m有前驱和后继
if(m->pre) m->pre->post=n;
}
inline void takeoutNode(Node *&n) //节点n从牌顶取走
{
if(n->down) //如果牌堆中有下一张牌
{
Node *down=n->down;
insertNode(n,down);
return;
}
if(n->pre) n->pre->post=n->post; //如果节点n有前驱和后继
if(n->post) n->post->pre=n->pre;
}
inline void inStackNode(Node *&m,Node *&n) //节点n放在节点m为堆顶的牌堆
{
n->size=m->size+1;
insertNode(m,n);
n->down=m;
}
inline bool checkMovable(Node *n,Node *m) //检查节点n和节点m是否匹配
{
return n->a==m->a || n->b==m->b;
}
inline void pre3(Node *&n) //左边第三张
{
if(n->pre) n=n->pre;
if(n->pre) n=n->pre;
if(n->pre) n=n->pre;
}
inline void pre1(Node *&n) //左边第一张
{
if(n->pre) n=n->pre;
}
inline void deleteNodes(Node *&n) //删除操作,用于每个测试用例之后,释放空间
{
while(n)
{
Node *p=n->post;
while(n)
{
Node *d=n->down;
delete n; n=NULL;
n=d;
}
n=p;
}
}
int main()
{
Node *head =new Node; //虚拟头节点
while(true)
{
Node *it =new Node;
it->a=getchar();
if(it->a=='#') break;
it->b=getchar();
getchar();
head->post=it; //链表初始化
it->pre=head;
for(int i=1;i<52;i++) //当前测试用例,52张牌构成线性链表
{
Node *p=new Node;
p->a=getchar();
p->b=getchar();
getchar();
it->post=p;
p->pre=it;
it=p;
}
bool checkMove=true;
while(checkMove) //移动牌规则
{
checkMove=false;
it=head->post;
while(it)
{
Node *post=it->post;
Node *p=it;
pre3(p); //左边第三张牌是否匹配
if(p && p!=head && checkMovable(p,it))
{
checkMove=true;
takeoutNode(it);
inStackNode(p,it);
break;
}
p=it;
pre1(p); //左边第一张牌是否匹配
if(p && p!=head && checkMovable(p,it))
{
checkMove=true;
takeoutNode(it);
inStackNode(p,it);
break;
}
it=post;
} //while(it)
} //while(checkMove && piles>1)
it=head->post;
int piles=0;
while(it) //游戏结束时的牌堆
{
piles++;
it=it->post;
}
if(piles==1) printf("%d piles remaining:",piles); //输出结果
else printf("%d piles remaining:",piles);
it=head->post;
while(it)
{
printf(" %d",it->size);
it=it->post;
}
putchar('n');
deleteNodes(head->post); //删除链表,释放空间
} //while(true)
delete head;
return 0;
}
D Broken Keyboard
#include <bits/stdc++.h>
using namespace std;
#define maxl 100005 //字符串最长长度
int main()
{
char s[maxl]; //输入的字符串
while(~scanf("%s",s+1)) //每次循环,处理一个测试用例
{
int Next[maxl]={0}; //链表初始化
int cur=0,last=0; //指针变量cur和last如试题解析所述
for(int i=1;s[i];++i) //输入的字符串逐个处理
{
if(s[i]=='[') cur=0; //'[',光标就跳到字符串的最前面
else if(s[i]==']') cur=last; //']',光标就跳到字符串的最后面
else
{
Next[i]=Next[cur]; //链表插入操作
Next[cur]=i;
if(cur==last) last=i; //last的更新
cur=i; //cur的更新
}
}
for(int i=Next[0];i!=0;i=Next[i]) //输出
if(s[i]!='[' && s[i]!=']')
printf("%c",s[i]);
printf("n");
}
return 0;
}
E Satellites
#include <iostream>
#include <cmath>
using namespace std;
const double r=6440; //地球半径
int main()
{
double ss,as; //ss:卫星与地球表面的距离; as:两颗卫星对地球中心的夹角
char s[10]; //保存"min"或"deg"
while(cin>>ss>>as>>s){
if(s[0]=='m')
as=as/60; //分转换为度
double angle = M_PI*as/180;
double arc=angle*(ss+r); //圆弧距离
double dis=2*(ss+r)*sin(angle/2); //直线弦距离
if(as>180) arc=2*M_PI*(ss+r)-arc; //夹角大于180度的情况
printf("%.6f %.6fn",arc,dis);
}
return 0;
}
F Fourth Point!!
#include <iostream>
using namespace std;
typedef struct
{
double x,y;
}point; //端点坐标
int main()
{
point a,b,c,d,e; //a,b,c,d:相邻边的端点
while(~scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y))
{
scanf("%lf%lf%lf%lf",&c.x,&c.y,&d.x,&d.y);
//调整,让b和c坐标相同
if(a.x==c.x && a.y==c.y)
swap(a,b);
if(a.x==d.x && a.y==d.y)
swap(a,b);swap(c,d);
if(b.x==d.x && b.y==d.y)
swap(c,d);
e.x = a.x+d.x-c.x; e.y = a.y+d.y-c.y; //第4个端点的坐标
printf("%.3lf %.3lfn",e.x,e.y);
}
return 0;
}
G The Circumference of the Circle
#include <stdio.h>
#include <math.h>
#define PI 3.141592653589793
double length_of_side(double x1,double y1,double x2,double y2) //求边长
{
double side;
side=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
return side;
}
double triangle_area(double side1,double side2,double side3) //求三角形面积:海伦公式
{
double p=(side1+side2+side3)/2;
double area=sqrt(p*(p-side1)*(p-side2)*(p-side3));
return area;
}
double diameter(double s,double a,double b,double c) //求直径
{
double diam;
diam=a*b*c/2/s;
return diam;
}
int main()
{
double x1,y1,x2,y2,x3,y3,side1,side2,side3,s,d;
while((scanf("%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3))!=EOF)
{
side1=length_of_side(x1,y1,x2,y2); //三角形三条边的边长
side2=length_of_side(x1,y1,x3,y3);
side3=length_of_side(x2,y2,x3,y3);
s=triangle_area(side1,side2,side3); //三角形面积
d=diameter(s,side1,side2,side3); //外接圆直径
printf("%.2lfn",PI*d); //外接圆周长
}
return 0;
}
H Titanic
#include <iostream>
#include <cmath>
using namespace std;
double dist(double l1,double d1,double l2,double d2) //计算两点距离
{
double r=6875.0/2; //地球半径
double p=acos(-1.0); //PI
l1*=p/180; d1*=p/180; //度转换为弧度
l2*=p/180; d2*=p/180;
return r*acos(cos(l1)*cos(l2)*cos(d1-d2)+sin(l1)*sin(l2)); //距离
}
int main()
{
char temp[100];
double d,m,s,l1,l2,d1,d2,dis;
for(int i=0;i<9;++i)
scanf("%s",temp);
scanf("%lf^%lf'%lf" %s",&d,&m,&s,temp); //船的位置
l1=d+m/60+s/3600; //转换为度
if(temp[0]=='S') //负方向
l1*=-1;
scanf("%s",temp);
scanf("%lf^%lf'%lf" %s.",&d,&m,&s,temp);
d1=d+m/60+s/3600; //转换为度
if(temp[0]=='W') d1*=-1; //负方向
for(int i=0;i<5;++i)
scanf("%s",temp);
scanf("%lf^%lf'%lf" %s",&d,&m,&s,temp); //冰山的位置
l2=d+m/60+s/3600;
if(temp[0]=='S')
l2*=-1;
scanf("%s",temp);
scanf("%lf^%lf'%lf" %s",&d,&m,&s,temp);
d2=d+m/60+s/3600;
if(temp[0]=='W')
d2*=-1;
scanf("%s",temp);
dis=dist(l1,d1,l2,d2); //船和冰山的距离
printf("The distance to the iceberg: %.2lf miles.n",dis);
if(floor(dis+0.005)<100) //距离小于100英里
printf("DANGER!n");
return 0;
}
Day 3
最后
以上就是受伤水壶为你收集整理的ICPC训练联盟2021寒假冬令营试题及源码答案Day 1Day 2Day 3的全部内容,希望文章能够帮你解决ICPC训练联盟2021寒假冬令营试题及源码答案Day 1Day 2Day 3所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复