冬令营第一天(1.18)

问题A: 专用四位数

查找并列出十进制表示法中所有四位数字,这些数字具有其四位数字的总和等于以十六进制表示法(基数 16)表示时等于其数字的总和的属性,也等于以二进制符号(基数 12)表示表示时表示其数字的总和。
例如,数字 2991 具有(十进制)数字 2+9+9+1 = 21 的总和。 自 2991 = 11728 = 8144 = 9*12 = 3 起,其双字表示形式为 189312,这些数字也汇总到 21。 但是在十六进制 2991 中是 BAF16,11+10+15 = 36,所以 2991 应该被你的程序拒绝。
但是,下一个数字 (2992) 在所有三种表示形式(包括 BB016)中都有总和 22 的数字,因此 2992 应放在列出的输出上。 (我们不希望小数数字少于四位数(不包括前导零),因此 2992 是第一个正确答案。

## 输入(无输入)

此问题没有输入

## 输出

您的输出为 2992,所有较大的四位数(严格增加顺序)将位于单独的行上,没有前导空格或尾随空格,以新行字符结尾。 输出中没有空白行。 输出的前几行如下所示。
示例输入
此问题没有输入
(部分)样品输出
2992
2993
2994
2995
2996
2997
2998
2999

参考代码:

#include <iostream>

using namespace std;

int main()
{
    
    
    for( int i = 1000; i <= 9999; i++ )
    {
    
    
        int s16 = 0, s12 = 0, s10 = 0;
        
        int ii = i;
        while( ii )
        {
    
    
            s16 += ii % 16;
            ii /= 16;
        }
        
        ii = i;
        while( ii )
        {
    
    
            s12 += ii % 12;
            ii /= 12;
        }
        
        if( s16 != s12 ) continue;
        
        ii = i;
        while( ii )
        {
    
    
            s10 += ii % 10;
            ii /= 10;
        }
        
        if( s16 == s10 ) printf( "%d\n", i );
    }
    return 0;
}

问题B: 猪拉丁语

您已经决定,PGP加密不够强大,您的电子邮件。您已决定先将明文字母转换为猪拉丁文,然后再使用 PGP 对其进行加密来补充它。

输入和输出
您将编写一个程序,该程序将包含任意数量的文本行,并在 Pig 拉丁语中输出它。每行文本将包含一个或多个单词。"单词"定义为连续的字母序列(上写字母和/或小写字母)。单词应根据以下规则转换为 Pig 拉丁语(非单词的输出应与输入中显示的完全一样):

1.以元音(a ,e ,i ,o,或u)开始的单词,以及这些单词的大写字母版本,应该只附加了字符串"ay"(不包括引号)。例如,“苹果"变成了"苹果”。
2.以辅子开头的单词(任何字母大于不是A、a、E、e、I、i、O、O、U或u)应删除第一个辅子并追加到单词的末尾,然后附加"ay"。例如,“hello”“变成"ellohay”。
3.不要更改任何字母的情况。
示例输入
This is the input.
样品输出
hisTay isay hetay inputay.

参考代码:

#include<cstdio>
#include<iostream>

using namespace std;
char s[1000005];
bool isvowel(char s){
    
    //判断是不是元音 
	if(s == 'a'|| s == 'e'|| s== 'i' || s== 'o' || s == 'u')
	return true ;
	return false ;
}

bool isaf(char s){
    
     // 判断是否是字母 
	if(s >= 'a' && s <= 'z') return true;
	if(s >= 'A' && s <= 'Z') return true;
	return false;
}

int main()
{
    
    
	while(gets(s)){
    
     // 多组输入 
		int a=0,t=0;
		while(s[a]){
    
    
			if(!isaf(s[a])) {
    
     // 如果不是字母,则直接输出 
				printf("%c",s[a++]);
				t=a;	
			}
			else if(isaf(s[t])){
    
     // 统计字母长度 
				t++;
			}
			else{
    
    
				if(isvowel(s[t])){
    
     // 进行加密 
					for(int i = a; i < t; i++) printf("%c",s[i]);
				}
				else{
    
    
					for(int i = a+1; i < t; i++) printf("%c",s[i]);
						printf("%c",s[a]);
				}				
					printf("ay");
					a=t;
			}
		}
		printf("\n");
	}
	return 0;
}

问题C:Tic Tac 脚趾

Tic Tac 脚趾是一个儿童游戏, 在 3 比 3 网格上玩。一个玩家 X 从将 X 放置在未占用的网格位置开始。然后,另一个玩家 O 将 O 放置到一个未占用的网格位置。在 X 和 O 之间播放交替,直到网格被填充或一个玩家的符号占据网格中的整条线(垂直、水平或对角线)。
我们将用九个点表示初始空的 Tic Tac 脚趾网格。每当 X 或 O 播放时,我们都会在适当的位置填充 X 或 O。下面的示例演示了从游戏开始到结束的每个网格配置,其中 X 获胜。
… Ⅹ。。 X. o X. o X. o X. o X. o X. o
… … … … .O. . o. Oo。 Oo。
… … … …Ⅹ。。X X. X. X X
你的工作是读取一个网格,并确定它是否可能是一个有效的Tic Tac脚趾游戏的一部分。也就是说,是否有一系列游戏可以在游戏的开始和结束之间产生这个网格?
第一行输入包含 N,即测试用例的数量。4N-1 行跟随,指定由空行分隔的 N 个网格配置。对于每个案例,在行上打印"是"或"否",指示配置是否可以是 Tic Tac Toe 游戏的一部分。
在这里插入图片描述
示例输入
2
X.O
OO.
XXX

O.X
XX.
OOO
样例输出
yes
no

参考代码:

#include <stdio.h>

char g[3][4];

int i,j,k,m,n,N,xcount,ocount;

int win(char c){
    
    
   int i,j;
   for (i=0;i<3;i++) {
    
    
      for (j=0;j<3 && g[i][j]==c;j++);
      if (j==3) return 1;
      for (j=0;j<3 && g[j][i]==c;j++);
      if (j==3) return 1;
   }
   for (i=0;i<3 && g[i][i]==c;i++);
   if (i==3) return 1;
   for (i=0;i<3 && g[i][2-i]==c;i++);
   if (i==3) return 1;
   return 0;
}

int main(){
    
    
   scanf("%d",&N);
   while (N--){
    
    
      scanf(" %s %s %s",g[0],g[1],g[2]);
      xcount = ocount = 0;
      for (i=0;i<3;i++) for (j=0;j<3;j++) {
    
    
         if (g[i][j] == 'X') xcount++;
         if (g[i][j] == 'O') ocount++;
      }
      /*printf("x %d o %d xwin %d owin %d\n",xcount,ocount,win('X'),win('O'));*/
      if (
         ocount > xcount || xcount > ocount + 1
         || win('X') && win('O') 
         || win('O') && xcount != ocount
         || win('X') && xcount == ocount
      ) {
    
    
         printf("no\n");
         continue;
      }
      printf("yes\n");
   }
   return 0;
}

问题D :

在这里插入图片描述
这题有个很无语的地方——n可以为负数。所以需要强行拓展关于阶乘的定义
factorial(n) = n ∗ factorial(n − 1)

利用题目中给出的这个公式,factorial(0) = 0 ∗ factorial(-1)。
再稍作变形factorial(-1) = factorial(0) / 0,所以-1的阶乘等于∞。继续按照这个思路扩展,factorial(-1) = -1 ∗ factorial(-2),所以-2的阶乘等于-∞。

以此类推,在n为负数的前提下,n如果是奇数答案就是Overflow!,如果是偶数答案就是Underflow!

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <string>
#include <cstring>
#include <map>
#include <vector>
#include <cmath>
 
using namespace std;
typedef long long ll;
 
ll fact[20];
 
int main() {
    
    
    // 13! = 6227020800
    // 7! < 10000 < 8!
    fact[0] = 1;
    for(int i=1;i<=13;i++)
        fact[i] = i * fact[i-1];

    int n;
    while(scanf("%d",&n)==1){
    
    
        if(n > 13 || (n < 0 && -1*n%2 == 1))
            printf("Overflow!\n");
        else if(n <= 7 || (n < 0 && -1*n%n == 0))
            printf("Underflow!\n");
        else
            printf("%lld\n",fact[n]);
    }
    return 0;
}

问题E:函数运行乐趣

我们都爱递归! 不是吗?
考虑一个三参数递归函数 w(a, b, c):

如果 a<= 0 或 b <= 0 或 c <= 0,则 w(a, b, c) 返回:
1

如果a > 20 或 b > 20 或 c > 20, 则 w (a, b, c) 返回:
w(20,20,20)

如果 a< b 和 b < c, 则 w (a, b, c) 返回:
w(a, b, c -1) = w (a, b - 1, c - 1) - w (a, b - 1, 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)

这是一个易于实现的功能。 问题是,如果直接实现,对于 a、b 和 c 的中等值(例如,a = 15,b = 15,c = 15),程序需要数小时才能运行,因为大量递归。
输入
程序的输入将是一系列整数三重,每行一个,直到文件末尾标志 -1 -1 -1。 使用上述技术,您可以有效地计算 w(a、b、c)并打印结果。 例如:

1 1 1
2 2 2
10 4 6
50 50 50
-1 7 18
-1 -1 -1
输出
打印每个三重的 w(a,b,c) 的值,像这样:

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

注意:当心可怕的运行时超过错误

简单递归,参考代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include <vector>
#include<stack>
#include<map>
#include<string>
#include<cstring>
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);
#define inf 0x3f3f3f3f
#define SC(a) scanf("%d",&a)
#define pr(a) printf("%d",a)
#define mem(a) memset(a,0,sizeof(a))
#define fn for(int i = 1; i <= n; i++)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 20;
int f[N+1][N+1][N+1];

int  w(int a, int b, int c)
{
    
    
	if(a <= 0 || b <= 0 || c <= 0) return true;
	else if(a > N || b > N || c > N) return w(N,N,N);
	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()
{
    
    
	mem(f);
	int a,b,c;
	while(~scanf("%d%d%d",&a,&b,&c)){
    
    
		if(a==-1&&b==-1&&c==-1)return 0;
		printf("w(%d, %d, %d) = %d\n",a,b,c,w(a,b,c));
	}
	return 0;
}

问题F:

在这里插入图片描述

#include <cstring>
#include <cstdio>

using namespace std;
typedef long long LL;
const int N = 1e5 + 10;

int sum(LL x)
{
    
    
    if(x < 1) return 0;
    return (x + 1) * (x - 1 + 1) / 2;//等差数列公式
}

int cal(int x)
{
    
    
    if(x <= 0) return 0;
    LL ans = 0;
    while(x)
    {
    
    
        //分类讨论1.1--9总和45  2.x的每一位都要进行计算
        ans += x / 10 * 45;
        ans += sum(x % 10);
        x /= 10;
    }
    return ans;
}

int main()
{
    
    
    int n, m;
    while(~scanf("%d%d", &n, &m) && (n != -1) && (m != -1))
    {
    
    
        //数据保证m > n
        printf("%d\n", cal(m) - cal(n - 1));   
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ecjtu2020/article/details/112789982