2021冬季集训

冬季集训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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值