## ICPC冬令营Day01

### A - Specialized Four-Digit Numbers

Find and list all four-digit numbers in decimal notation that have the property that the sum of its four digits equals the sum of its digits when represented in hexadecimal (base 16) notation and also equals the sum of its digits when represented in duodecimal (base 12) notation.

For example, the number 2991 has the sum of (decimal) digits 2+9+9+1 = 21. Since 2991 = 1*1728 + 8*144 + 9*12 + 3, its duodecimal representation is 189312, and these digits also sum up to 21. But in hexadecimal 2991 is BAF16, and 11+10+15 = 36, so 2991 should be rejected by your program.

The next number (2992), however, has digits that sum to 22 in all three representations (including BB016), so 2992 should be on the listed output. (We don’t want decimal numbers with fewer than four digits – excluding leading zeroes – so that 2992 is the first correct answer.)

#### Input

There is no input for this problem

#### Output

Your output is to be 2992 and all larger four-digit numbers that satisfy the requirements (in strictly increasing order), each on a separate line with no leading or trailing blanks, ending with a new-line character. There are to be no blank lines in the output. The first few lines of the output are shown below.

#### Sample Input

`There is no input for this problem`

#### Sample Output

```
2992
2993
2994
2995
2996
2997
2998
2999
...
```

#### 问题分析：

水题，简单递归，找到满足12进制，10进制，16进制的各个位数字和相同的四位数字输出即可。

#### AC代码：

```
#include<iostream>
using namespace std;
int solve(int number,int base){
int ans = 0;
while(number){
ans += number % base;
number /= base;
}
return ans;
}
int main(){
for(int i = 2991 ; i <= 9999 ; i++){
if(solve(i,10) == solve(i,12) && solve(i,12) == solve(i,16))
cout << i << endl;
}
return 0;
}
```

### C - Tic Tac Toe

Tic Tac Toe is a child’s game played on a 3 by 3 grid. One player, X, starts by placing an X at an unoccupied grid position. Then the other player, O, places an O at an unoccupied grid position. Play alternates between X and O until the grid is filled or one player’s symbols occupy an entire line (vertical, horizontal, or diagonal) in the grid.

We will denote the initial empty Tic Tac Toe grid with nine dots. Whenever X or O plays we fill in an X or an O in the appropriate position. The example below illustrates each grid configuration from the beginning to the end of a game in which X wins.

```
... X.. X.O X.O X.O X.O X.O X.O
... ... ... ... .O. .O. OO. OO.
... ... ... ..X ..X X.X X.X XXX
```

Your job is to read a grid and to determine whether or not it could possibly be part of a valid Tic Tac Toe game. That is, is there a series of plays that can yield this grid somewhere between the start and end of the game?

#### Input

The first line of input contains N, the number of test cases. 4N-1 lines follow, specifying N grid configurations separated by empty lines.

#### Output

For each case print “yes” or “no” on a line by itself, indicating whether or not the configuration could be part of a Tic Tac Toe game.

#### Sample Input

```
2
X.O
OO.
XXX
O.X
XX.
OOO
```

#### Sample Output

```
yes
no
```

#### 题意:

给出一个已经下好的三连棋的棋盘，判断是否符合条件。

#### 题目分析：

首先，我们知道三连棋第一个下的必须是X，那么仔细观察不难发现，不满足条件的情况一共只有四种：

```
1.X的数量小于O
2.X的数量与O的数量相差超过1
3.当X胜利时X的数量与O的数量差值不为1
4.当O胜利时X的数量和O的数量不相等(画画图就知道了，O想赢必须要保证X和O的数量一致)
```

判断输赢只需要判断横向，纵向，或者对角线是否存在三个连在一起的棋子即可

**判断代码：**

```
int judgeWin(char c){
for(int i = 0 ; i < 3 ; i++){
if(mp[i][0] == c && mp[i][1] == c && mp[i][2] == c){
return 1;
}
}
for(int i = 0 ; i < 3 ; i++){
if(mp[0][i] == c && mp[1][i] == c && mp[2][i] == c){
return 1;
}
}
if(mp[0][0] == c && mp[1][1] == c && mp[2][2] == c){
return 1;
}
if(mp[0][2] == c && mp[1][1] == c && mp[2][0] == c){
return 1;
}
return 0;
}
```

#### AC代码：

```
#include<iostream>
using namespace std;
char mp[3][3];
int t,xcnt,ocnt,f;
int judgeWin(char c){
for(int i = 0 ; i < 3 ; i++){
if(mp[i][0] == c && mp[i][1] == c && mp[i][2] == c){
return 1;
}
}
for(int i = 0 ; i < 3 ; i++){
if(mp[0][i] == c && mp[1][i] == c && mp[2][i] == c){
return 1;
}
}
if(mp[0][0] == c && mp[1][1] == c && mp[2][2] == c){
return 1;
}
if(mp[0][2] == c && mp[1][1] == c && mp[2][0] == c){
return 1;
}
return 0;
}
int main(){
cin >> t;
while(t--){
ocnt = xcnt = 0;
for(int i = 0 ; i < 3 ; i++){
for(int j = 0 ; j < 3 ; j++){
cin >> mp[i][j];
if(mp[i][j] == 'O') ocnt++;
else if(mp[i][j] == 'X') xcnt++;
}
}
if((judgeWin('X') && xcnt - ocnt != 1) || (judgeWin('O') && xcnt != ocnt) || (xcnt < ocnt) || (xcnt - ocnt > 1)){
cout << "no" << endl;
}else{
cout << "yes" << endl;
}
}
return 0;
}
```

### D - Factorial! You Must be Kidding!!!

Arif has bought a super computer from Bongobazar. Bongobazar is a place in Dhaka where second hand goods are found in plenty. So the super computer bought by him is also second hand and has some bugs. One of the bugs is that the range of unsigned long integer of this computer for C/C++ compiler has changed. Now its new lower limit is 10000 and upper limit is 6227020800. Arif writes a program in C/C++ which determines the factorial of an integer. Factorial of an integer is defined recursively as: f actorial(0) = 1 f actorial(n) = n ∗ f actorial(n − 1). Of course one can manipulate these expressions. For example, it can be written as f actorial(n) = n ∗ (n − 1) ∗ f actorial(n − 2) This definition can also be converted to an iterative one. But Arif knows that his program will not behave rightly in the super computer. You are to write program which will simulate that changed behavior in a Normal Computer.

#### Input

The input file contains several lines of input. Each line contains a single integer n. No integer has more than six digits. Input is terminated by end of file.

#### Output

For each line of input you should output a single line. This line will contain a single integer n! if the value of n! fits within the unsigned long integer of Arif’s computer. Otherwise the line will contain one of the following two words Overflow! (When n! > 6227020800) Underflow! (When n! < 10000)

#### Sample Input

```
2
10
100
```

#### Sample Output

```
Underflow!
3628800
Overflow!
```

### E - Function Run Fun

We all love recursion! Don’t we?

Consider a three-parameter recursive function w(a, b, c):

if a <= 0 or b <= 0 or c <= 0, then w(a, b, c) returns:

1

if a > 20 or b > 20 or c > 20, then w(a, b, c) returns:

w(20, 20, 20)

if a < b and b < c, then w(a, b, c) returns:

w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c)

otherwise it returns:

w(a-1, b, c) + w(a-1, b-1, c) + w(a-1, b, c-1) - w(a-1, b-1, c-1)

This is an easy function to implement. The problem is, if implemented directly, for moderate values of a, b and c (for example, a = 15, b = 15, c = 15), the program takes hours to run because of the massive recursion.

#### Input

The input for your program will be a series of integer triples, one per line, until the end-of-file flag of -1 -1 -1. Using the above technique, you are to calculate w(a, b, c) efficiently and print the result.

#### Output

Print the value for w(a,b,c) for each triple.

#### Sample Input

```
1 1 1
2 2 2
10 4 6
50 50 50
-1 7 18
-1 -1 -1
```

#### Sample Output

```
w(1, 1, 1) = 2
w(2, 2, 2) = 4
w(10, 4, 6) = 523
w(50, 50, 50) = 1048576
w(-1, 7, 18) = 1
```

#### 问题分析：

记忆化搜索+递归，由于a,b,c最多不会超过20，所以使用三维数组进行标记，将所有计算过的w(a,b,c)，全部记忆化，这样下次再使用这个w(a,b,c)时就不需要再重新计算了。

**记忆化代码：**

```
ll w(int a,int b,int c){
if(a <= 0 || b <= 0 || c <= 0) return 1;
else if(a > 20 || b > 20 || c > 20) return w(20,20,20);
else if(f[a][b][c]) return f[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);
}
```

#### AC代码：

```
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll f[21][21][21];
ll a,b,c;
ll w(int a,int b,int c){
if(a <= 0 || b <= 0 || c <= 0) return 1;
else if(a > 20 || b > 20 || c > 20) return w(20,20,20);
else if(f[a][b][c]) return f[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(){
while((cin >> a >> b >> c) && !(a == -1 && b == -1 && c == -1)){
cout << "w(" << a <<", "<< b << ", " << c << ") = " << w(a,b,c) << endl;
}
return 0;
}
```

### G - A Contesting Decision

Judging a programming contest is hard work, with demanding contestants, tedious decisions,and monotonous work. Not to mention the nutritional problems of spending 12 hours with only donuts, pizza, and soda for food. Still, it can be a lot of fun.

Software that automates the judging process is a great help, but the notorious unreliability of some contest software makes people wish that something better were available. You are part of a group trying to develop better, open source, contest management software, based on the principle of modular design.

Your component is to be used for calculating the scores of programming contest teams and determining a winner. You will be given the results from several teams and must determine the winner.**Scoring**

There are two components to a team’s score. The first is the number of problems solved. The second is penalty points, which reflects the amount of time and incorrect submissions made before the problem is solved. For each problem solved correctly, penalty points are charged equal to the time at which the problem was solved plus 20 minutes for each incorrect submission. No penalty points are added for problems that are never solved.

So if a team solved problem one on their second submission at twenty minutes, they are charged 40 penalty points. If they submit problem 2 three times, but do not solve it, they are charged no penalty points. If they submit problem 3 once and solve it at 120 minutes, they are charged 120 penalty points. Their total score is two problems solved with 160 penalty points.

The winner is the team that solves the most problems. If teams tie for solving the most problems,then the winner is the team with the fewest penalty points.

#### Input

For the programming contest your program is judging, there are four problems. You are guaranteed that the input will not result in a tie between teams after counting penalty points.

Line 1 < nTeams >

Line 2 - n+1 < Name > < p1Sub > < p1Time > < p2Sub > < p2Time > … < p4Time >

The first element on the line is the team name, which contains no whitespace.Following that, for each of the four problems, is the number of times the team submitted a run for that problem and the time at which it was solved correctly (both integers). If a team did not solve a problem, the time will be zero. The number of submissions will be at least one if the problem was solved.

#### Output

The output consists of a single line listing the name of the team that won, the number of problems they solved, and their penalty points.

#### Sample Input

```
4
Stars 2 20 5 0 4 190 3 220
Rockets 5 180 1 0 2 0 3 100
Penguins 1 15 3 120 1 300 4 0
Marsupials 9 0 3 100 2 220 3 80
```

#### Sample Output

`Penguins 3 475`

#### 题目分析：

这是一道很简单排序题目，每个队伍做4道题目，给出每道题目提交的次数以及提交成功的时间，如果题目最后提交成功的时间为0，表示题目没有AC，那么前面的罚时也不算。罚时只对那些做出来的题目有效。最后只要输出成绩最好的队伍的名称，做出题目数量，以及时间即可。排序设置两个关键字，先根据做出题目数量从大到小排序，如果题目数量一致就根据罚时从小到大排序。

**排序代码：**

```
struct team{
string name;
int p1Sub,p1Time,p2Sub,p2Time,p3Sub,p3Time,p4Sub,p4Time,corSum,timeSum;
}teams[maxn];
bool cmp(team t1,team t2){
if(t1.corSum != t2.corSum)
return t1.corSum > t2.corSum;
return t1.timeSum < t2.timeSum;
}
```

#### AC代码：

```
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 1e4+5;
int n;
struct team{
string name;
int p1Sub,p1Time,p2Sub,p2Time,p3Sub,p3Time,p4Sub,p4Time,corSum,timeSum;
}teams[maxn];
bool cmp(team t1,team t2){
if(t1.corSum != t2.corSum)
return t1.corSum > t2.corSum;
return t1.timeSum < t2.timeSum;
}
int main(){
cin >> n;
for(int i = 0 ; i < n ; i++){
cin >> teams[i].name >> teams[i].p1Sub >> teams[i].p1Time >> teams[i].p2Sub >> teams[i].p2Time >> teams[i].p3Sub >> teams[i].p3Time >> teams[i].p4Sub >> teams[i].p4Time;
if(teams[i].p1Time != 0) teams[i].corSum++,teams[i].timeSum += (20*(teams[i].p1Sub-1) + teams[i].p1Time);
if(teams[i].p2Time != 0) teams[i].corSum++,teams[i].timeSum += (20*(teams[i].p2Sub-1) + teams[i].p2Time);
if(teams[i].p3Time != 0) teams[i].corSum++,teams[i].timeSum += (20*(teams[i].p3Sub-1) + teams[i].p3Time);
if(teams[i].p4Time != 0) teams[i].corSum++,teams[i].timeSum += (20*(teams[i].p4Sub-1) + teams[i].p4Time);
}
sort(teams,teams+n,cmp);
cout << teams[0].name << " " << teams[0].corSum << " " << teams[0].timeSum << endl;
return 0;
}
```

**本文链接：**http://111.230.202.9/2021/01/18/ICPC%E5%86%AC%E4%BB%A4%E8%90%A5Day01/**版权声明：**本博客所有文章除特别声明外，均默认采用 许可协议。

若没有本文 Issue，您可以使用 Comment 模版新建。

GitHub IssuesGitHub Discussions