T1
命名那个数字 Name That Number
题意
每个数字上都有一些字母,类似手机按键的。给出一堆名字和一串数字,判断根据这些数字能按到这些名字中的哪些。
思路
搜索每种数字的可能,再判断。
或一个一个名字的判断,看看能不能从这些数字中按出。
这里我用了搜索,效率比第二种方法低。
代码
#include<map>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int a[15];
int l, k, ans;
char ch[15];
map<string, bool> f;
char letter[11][3]={{},{},{'A','B','C'},{'D','E','F'},{'G','H','I'},{'J','K','L'},{'M','N','O'},{'P','R','S'},{'T','U','V'},{'W','X','Y'}};
string p[5000], str;
void dfs(string ans, int len) {
if(len == l + 1) {//判断有没有这个名字
if(!f[ans]) return;
else p[++k] = ans;
return;
}
for(int i = 0; i < 3; i++)//搜索这个数字的三个字母
dfs(ans + letter[a[len]][i], len + 1);
}
int main()
{
scanf("%s", ch + 1);
l = strlen(ch + 1);
while (cin>>str) f[str] = 1;
for(int i = 1; i <= l; i++) a[i] = ch[i] - '0';
dfs("", 1);
if(!k) printf("NONE");
else {
sort(p, p + 1 + k);
for(int i = 1; i <= k; i++) cout<<p[i]<<endl;
}
}
T2
挤牛奶Milking Cows
题意
有 N N N个人会在 x ∼ y x\sim y x∼y的时间给牛挤奶,求最长的没人挤奶的一段和有人挤奶的一段。
思路
我们可以用前缀和的思想。在 a [ x ] + 1 a[x]+1 a[x]+1, a [ y ] − 1 a[y]-1 a[y]−1,统计前缀和时就可以求出这时有没有人挤奶,然后就可以求出答案。
代码
#include<cstdio>
#include<algorithm>
using namespace std;
int N, s = 1000001, e, ans1, ans2, t1, t2;
int a[1000001];
int main() {
scanf("%d", &N);
int x, y;
for (int i = 1; i <= N; i++) {
scanf("%d %d", &x, &y);
a[x]++;
a[y]--;
s = min(s, x);
e = max(e, y);
}
for (int i = s; i <= e; i++) {
a[i] += a[i - 1];
if (a[i]) {//此时有人挤奶就要清空最长没人挤奶的答案
ans2 = max(t2, ans2);
t2 = 0;
t1++;//同时统计有人挤奶的答案
}
else {//同上
ans1 = max(t1, ans1);
t1 = 0;
t2++;
}
}
printf("%d %d", ans1, ans2);
}
T3
方块转换 Transformations
题意
给出两个矩阵,判断通过 7 7 7中操作能不能把第一个转成第二个。操作详见题目。
思路
7 7 7个判断就好了。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int N;
char a[11][11], b[11][11];
char c;
int check1() {
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
if (a[i][j] != b[j][N - i + 1]) return 0;
return 1;
}
int check2() {
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
if (a[i][j] != b[N - i + 1][N - j + 1]) return 0;
return 1;
}
int check3() {
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
if (a[i][j] != b[N - j + 1][i]) return 0;
return 1;
}
int check4() {
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
if (a[i][N - j + 1] != b[i][j]) return 0;
return 1;
}
int check5() {
int f = 0;
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N / 2; j++)
swap(a[i][N - j + 1], a[i][j]);
if (check1()) f = 1;
else if (check2()) f = 1;
else if (check3()) f = 1;
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N / 2; j++)
swap(a[i][N - j + 1], a[i][j]);
return f;
}
int check6() {
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
if (a[i][j] != b[i][j]) return 0;
return 1;
}
int main() {
scanf("%d", &N);
for (int i = 1; i <= N; i++)
scanf("%s", a[i] + 1);
for (int i = 1; i <= N; i++)
scanf("%s", b[i] + 1);
if (check1()) printf("1");
else if (check2()) printf("2");
else if (check3()) printf("3");
else if (check4()) printf("4");
else if (check5()) printf("5");
else if (check6()) printf("6");
else printf("7");
}
T4
回文平方数 Palindromic Squares
题意
给出一个进制。求出 1 ∼ 300 1\sim 300 1∼300中的平方在这个进制下是回文串的数。
思路
转换进制然后判断是不是回文串。
代码
#include<cstdio>
#include<cstring>
using namespace std;
int B;
void print(int N, int a[]) {
for (int i = N; i >= 1; i--)
if (a[i] > 9) putchar(a[i] + 55);
else printf("%d", a[i]);
}
void check(int s) {
int N1 = 0, N = 0, f = 1, x = s * s;
int a[11], b[11];
for (int t = x; t; t /= B) a[++N] = t % B;//进制转换
for (int i = 1; i <= N; i++) if (a[i] != a[N - i + 1]) f = 0;//判断回文
if (f) {
for (; s; s /= B) b[++N1] = s % B;
print(N1, b);//输出这个数
printf(" ");
print(N, a);//它的平方
printf("\n");
}
}
int main() {
scanf("%d", &B);
for (int i = 1; i <= 300; i++) check(i);
}
T5
双重回文数 Dual Palindromes
题意
找到前
N
N
N个大于
S
S
S的双重回文数。
定义:双重回文数为一个数在至少两种进制下都为回文数的数。
思路
根据定义来枚举判断。
代码
#include<cstdio>
#include<cstring>
using namespace std;
int N, S, ans;
int check(int s, int B) {//判断在B进制下是否问回文数
int N = 0, f = 1;
int a[101];
for (; s; s /= B) a[++N] = s % B;
for (int i = 1; i <= N; i++) if (a[i] != a[N - i + 1]) f = 0;
return f;
}
int main() {
scanf("%d %d", &N, &S);
for (int i = S + 1; ans != N; i++) {//枚举
int f = 0;
for (int j = 2; j <= 10 && f != 2; j++) if (check(i, j)) f++;//找两个进制
if (f == 2) {
ans++;
printf("%d\n", i);
}
}
}