问题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;
}