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位数字(以严格的递增序列),
每个数字一行,数字前后不加空格,以行结束符结束。
输出没有空行。输出的前几行如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#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输出。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48#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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59#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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56#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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136#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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30#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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#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!!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36#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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44#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内容请搜索靠谱客的其他文章。
发表评论 取消回复