冬季集训1.18
A - Specialized Four-Digit Numbers
通过调用函数来计算m进制的四位数字之和
int cal(int size,int x){
int sum = 0;
for(;x;x = x/size)
sum+=x%size;
return sum;
}
如果10进制4位数字和等于16与12进制数字和,符合题意,输出数字
for(int i = 2992;i<=9999;++i){
if(cal(10,i)==cal(16,i)&&cal(10,i)==cal(12,i))
cout<<i<<endl;
}
完整代码
#include<iostream>
using namespace std;
int cal(int size,int x){
int sum = 0;
for(;x;x = x/size)
sum+=x%size;
return sum;
}
int main(){
for(int i = 2992;i<=9999;++i){
if(cal(10,i)==cal(16,i)&&cal(10,i)==cal(12,i))
cout<<i<<endl;
}
return 0;
}
时间复杂度:共n个数字,每个数字需要调用三次函数,所以总体复杂度共O(n)
B - Pig-Latin
如果是单词通过判断每个单词首字母是否是元音字母,做出相应的处理,如果不是字母,正常输出
主要代码判断是元音字母,做出相应处理
if (isalpha(str[i])) {
char c = str[i];
tolower(c);
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
for (; str[i] != ' ' && str[i] != '\0'; ++i) {
s += str[i];
}
完整代码:
#include<iostream>
#include<cctype>
#include<string>
using namespace std;
string str, s;
int main() {
while (getline(cin,str)) {
int len = str.length(), i = 0;
while (i <= len) {
if (isalpha(str[i])) {
char c = str[i];
tolower(c);
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
for (; str[i] != ' ' && str[i] != '\0'; ++i) {
s += str[i];
}
--i;
s += "ay";
cout << s;
s.clear();
}
else {
string x;
x += str[i];
for (i = i + 1; str[i] != ' '; ++i) {
s += str[i];
}
--i;
s += x + "ay";
cout << s;
s.clear();
}
}
else {
cout << str[i];
}
++i;
}
}
return 0;
}
时间复杂度:O(n)
C - Tic Tac Toe
题目问给的棋盘是否是无效的,棋盘有效:'O‘数目小于’X’数目,’X’数目比‘O’数目多1,玩家 O不可能赢,‘X’,‘O’数目相等,玩家X不可能赢
主要代码:对棋盘上的x和o计数
for(int i = 0;i<3;++i){
for(int j = 0;j<3;++j){
if(mp[i][j]=='X') cntx++;
else if(mp[i][j]=='O')cnto++;
}
}
判断是否某个玩家赢了
int win(char c){
for(int i = 0;i<3;++i){
int j;
for(j = 0;j<3&&mp[i][j]==c;++j);//行相同
if(j==3) return 1;
for(j = 0;j<3&&mp[j][i]==c;++j);//列相同
if(j==3) return 1;
}
int i;
for(i = 0;i<3&&mp[i][i]==c;++i);//主对角线
if(i==3) return 1 ;
for(i = 0;i<3&&mp[i][2-i]==c;++i);//副对角线
if(i==3) return 1;
return 0;
}
完整代码:
#include<iostream>
using namespace std;
const int N = 1000;
char mp[N][N];
int flag;
int win(char c){
for(int i = 0;i<3;++i){
int j;
for(j = 0;j<3&&mp[i][j]==c;++j);//行相同
if(j==3) return 1;
for(j = 0;j<3&&mp[j][i]==c;++j);//列相同
if(j==3) return 1;
}
int i;
for(i = 0;i<3&&mp[i][i]==c;++i);//主对角线
if(i==3) return 1 ;
for(i = 0;i<3&&mp[i][2-i]==c;++i);//副对角线
if(i==3) return 1;
return 0;
}
int main(){
int n;
cin>>n;
while(n--){
int cntx=0,cnto=0;
for(int i = 0;i<3;++i)
scanf("%s",mp[i]);
for(int i = 0;i<3;++i){
for(int j = 0;j<3;++j){
if(mp[i][j]=='X') cntx++;
else if(mp[i][j]=='O')cnto++;
}
}
flag = 1;
if(cntx==cnto||cntx==cnto+1){
if(cntx==cnto){
if(win('X')) flag = 0;
}else{
if(win('O')) flag = 0;
}
}else flag = 0;
printf("%s\n",flag?"yes":"no");
}
}
时间复杂度:O(n^2)
D - Factorial! You Must be Kidding!!!
递归函数:
long long f(int x) {
if (x == 0) return 1;
else return x * f(x - 1);
}
完整代码:
#include<iostream>
#include<cstdio>
using namespace std;
int n;
long long f(int x) {
if (x == 0) return 1;
else return x * f(x - 1);
}
int main() {
while ((scanf_s"%d", &n)) != EOF) {
if (n >= 14 || (n < 0 && (-n) % 2 == 1)) cout << "Overflow!" << endl;
else if (n <= 8 || (n < 0 && (-n) % 2 == 0)) cout << "Underflow!" << endl;
else printf("%lld\n", f(n));
}
return 0;
}
E - Function Run Fun
通过题目给的要求来递归,因为需要大量递归,所以采用记忆化搜索,用f[a][b][c]来记忆递归结果
int w(int a, int b, int c)
{
if (f[a][b][c] != 0)
return f[a][b][c];
if (a <= 0 || b <= 0 || c <= 0)
return f[a][b][c] = 1;
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);
}
完整代码:
#include <cstdio>
#include <cstring>
const int maxn= 100;
int f[maxn][maxn][maxn];
int w(int a, int b, int c)
{
if (f[a][b][c] != 0)
return f[a][b][c];
if (a <= 0 || b <= 0 || c <= 0)
return f[a][b][c] = 1;
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()
{
int a, b, c;
int ans = 0;
while (scanf_s("%d %d %d", &a, &b, &c) != EOF)
{
if (a == -1 && b == -1 && c == -1)
break;
memset(f, 0, sizeof(f));
if (a <= 0 || b <= 0 || c <= 0)
ans = 1;
else
if (a > 20 || b > 20 || c > 20)
ans = w(20, 20, 20);
else
ans = w(a, b, c);
printf("w(%d, %d, %d) = %d\n", a, b, c, ans);
}
return 0;
}
G - A Contesting Decision
找解题数最多的,存在多个找罚时最少的
结构体部分:
struct team {
string tname;
int num[maxn];//每题提交次数
int t[maxn];//解题时间
int cnt,time;//解题成功数,罚时
}T[200];
完整代码:
#include<iostream>
#include<string>
using namespace std;
const int maxn = 30;
int n;
struct team {
string tname;
int num[maxn];//提交次数
int t[maxn];//解题时间
int cnt,time;
}T[200];
int main() {
cin>>n;
for (int i = 1; i <= n; ++i) {
cin >> T[i].tname;
for (int j = 1; j <= 4; ++j) {
cin >> T[i].num[j] >> T[i].t[j];
T[i].cnt = 0, T[i].time = 0;
}
for (int j = 1; j <= 4; ++j) {
if (T[i].t[j] != 0) {
T[i].cnt++;
T[i].time += T[i].t[j] + (T[i].num[j] - 1) * 20;
}
}
}
string winname;
int winnum = -1, wintime = 999999999;
for (int i = 1; i <= n; ++i) {
if (T[i].cnt>= winnum && T[i].time < wintime) {
winnum = T[i].cnt;
wintime = T[i].time;
winname = T[i].tname;
}
}
cout << winname << " " << winnum << " " << wintime << endl;
return 0;
}