B-1 数字命理计算器
西方人也讲数字命理,把人名对应到 11 个数字上,不同数字对应不同命运。这个数字集合包括 1 到 9、以及两个特殊的数字 11 和 22。
他们把名字里每个英文字母按序号(1~26)循环对应 1~9(例如 a 对应 1,i 对应 9,j 对应 1,r 对应 9,s 对应 1,等等),然后加起来。如果这个和不是命理数字集合里的数,就把这个数的各位数字相加,如此反复直到得到一个命理数。
本题就请你实现这个计算器。
输入格式:
输入第一行给出不超过 10 的正整数 n,随后 n 行,每行给出一个人名。每个人名由英文大小写字母和空格组成,至少有 1 个英文字母,一共不超过 100 个字符。
输出格式:
对每个人名,在对应的一行中输出其命理数。
输入样例:
4
Alan Turing
Pythagoras
Von Neumann
John Fox
输出样例:
9
4
7
11
AC代码:
change函数用于更新sum不符合要求(即不符合sum≥1 && sum ≤ 9 || sum == 11 || sum == 22)的值。使用getline函数确保录入一整行字符串。之后就是判断当前的字符的“命理数”,记得对9取模之后加1。
#include "bits/stdc++.h"
using namespace std;
int change(int num);
int main()
{
int n;
cin >> n;
getchar();
for(int i = 0; i < n; i++)
{
string name;
getline(cin, name);
int sum = 0;
for(int j = 0; j < name.length(); j++)
{
if(name[j] >= 'a' && name[j] <= 'z'){
sum += ((name[j] - 'a') % 9 + 1);
}else if(name[j] >= 'A' && name[j] <= 'Z'){
sum += ((name[j] - 'A') % 9 + 1);
}
}
while((sum < 1 || sum > 9) && sum != 11 && sum != 22){
sum = change(sum);
}
cout << sum << endl;
}
return 0;
}
int change(int num)
{
int sum = 0;
while(num != 0){
sum += (num % 10);
num /= 10;
}
return sum;
}
B-2 这也行
输入格式:
输入首先在第一行给出一个正整数 n(≤10),随后给出 n 个 2×2 矩阵的元素。每个矩阵分 2 行给出,每行有 2 个小于 10 的正整数。
输出格式:
对每个输入的矩阵,在一行中输出判断的结果:如果满足题面要求则输出 1,否则输出 0。
输入样例:
3
2 3
6 9
1 2
3 4
3 4
6 8
输出样例:
1
0
1
AC代码:
根据条件找准a、b、c、d直接进行if判断即可。
#include "bits/stdc++.h"
using namespace std;
int main()
{
int n;
cin >> n;
for(int i = 0; i < n; i++)
{
int a, b, c, d;
cin >> a >> b >> c >> d;
if(a * a + b * c == a *10 + a && a * b + b * d == b * 10 + b && c * a + d * c == c * 10 + c && c * b + d * d == d * 10 + d){
cout << 1 << endl;
}else{
cout << 0 << endl;
}
}
return 0;
}
B-3 有多少零
给定 n 个正整数,请你数数它们的乘积的末尾有多少个零。例如 26、225、48 的乘积是 280800,末尾有 2 个零。
输入格式:
输入给出一个不超过 106 的正整数 n,下一行给出 n 个不超过 106 的正整数。
输出格式:
在一行中输出给定的 n 个正整数的乘积末尾零的个数。
输入样例:
17
10 18 11 12 14 3 4 5 6 13 7 8 9 15 16 2 17
输出样例:
3
AC代码:
因为10是由5和2构成的,计算乘积末尾有多少0,就是需要统计每一个乘积的因子中包含多少2和5,最后求2和5较小的个数,这样就是最多能够构成2 * 5 = 10也就是末尾0的个数。
#include "bits/stdc++.h"
using namespace std;
int main()
{
int n;
cin >> n;
int mod5 = 0;
int mod2 = 0;
for(int i = 0; i < n; i++)
{
int num;
cin >> num;
while(num % 5 == 0){
mod5++;
num /= 5;
}
while(num % 2 == 0){
mod2++;
num /= 2;
}
}
cout << min(mod5, mod2);
return 0;
}
B-4 换位与质因数
给定一个正整数 n,任选其十进制表示中某两位不同的数字交换位置,得到另一个整数 m。问 m 的质因数集合与 n 的质因数集合有多大交集?
例如 n=623457198 时,我们可以算出其质因数集合为 A = {2, 3, 7, 13, 380621}。如果将 2 和 9 交换得到 m=693457128,其质因数集合为 B = {2, 3, 7, 13, 109, 971}。则 A 和 B 的交集为 {2, 3, 7, 13},有 4 个因子。
输入格式:
输入在一行中给出一个正整数 n(10<n≤109)。题目保证 n 至少有 2 个位置上的数字不相等。
输出格式:
将 n 的任意两位不同数字交换位置后得到数字 m,找到其质因数集合与 n 的质因数集合有最大交集的那个 m。在一行中输出交集中质因子的个数和 m,其间以 1 个空格分隔,行首尾不得有多余空格。如果这样的 m 不唯一,则输出数值最小者。
输入样例:
623457198
输出样例:
4 123457698
样例解释:
交集最大有 4 个因子的 m 有两个。除了题面中给出的数字外,还可以交换 6 和 1,得到的 123457698 的质因数集合为 {2, 3, 7, 13, 23, 29, 113},交集也是 {2, 3, 7, 13},且这个数字比 693457128 小,故输出。
AC代码:
首先初始化足够多素数放入vector集合中,然后录入n,用flag数组将n的质因数保存起来,将质因数存在的索引的值设置为1,不存在的保留初始化的0,方便后续判断。而后利用to_string()方法将n转换为字符串,利用swap函数交换位置,判断得到的数和n不相等,然后从vector集合中找出其对应的质因数,如果当前的质因数个数大于当前的maxValue值或当前的质因数个数等于当前的maxValue值且当前数小于maxNum值都对maxValue和maxNum进行修改,每次换位之前记得将字符串进行复位,最后打印输出即可。
#include "bits/stdc++.h"
using namespace std;
vector<int> prime;
int flag[1000005] = {0};
int isPrime(int n);
void Init()
{
for(int i = 2; i <= 1000000; i++){
if(isPrime(i)){
prime.push_back(i);
}
}
}
int main()
{
int n;
cin >> n;
Init();
for(int i = 0; i < prime.size(); i++){
if(n % prime[i] == 0){
flag[prime[i]] = 1;
}
}
string num = to_string(n);
int maxValue = 0;
int maxNum = 1000000001;
for(int i = 0; i < num.length(); i++)
{
for(int j = i + 1; j < num.length(); j++)
{
swap(num[i], num[j]);
int temp = stoi(num);
if(temp == n){
continue;
}
int cnt = 0;
for(int k = 0; k < prime.size(); k++){
if(flag[prime[k]] == 1 && temp % prime[k] == 0){
cnt++;
}
}
if(cnt > maxValue || (cnt == maxValue && temp < maxNum)){
maxValue = cnt;
maxNum = temp;
}
num = to_string(n);
}
}
cout << maxValue << " " << maxNum << endl;
return 0;
}
int isPrime(int n)
{
if(n == 0 || n == 1)
return 0;
for(int i = 2; i <= sqrt(n); i++){
if(n % i == 0)
return 0;
}
return 1;
}
B-5 程序员找失主
上图是一位捡到包的程序员给失主留的纸条,用了非常妙的双向加密:“在楼下捡了一个包,请失主看到了联系我!号码:1832834xxxx”,并注明前两个“xx”是“你身份证号第8-9位”,后面一个“x”是“你身份证号第五位”,最后一个“x”是“你身份证上最后一位”。
给定这位程序员的完整手机号码,以及一大群人的身份证号,请你找出那位失主。
输入格式:
输入首先在第一行给出程序员的 11 位数手机号码。第二行给出正整数 n(≤105),随后 n 行,每行给出一个 18 位身份证号。出于隐私保护,身份证号并不是真的,仅保证每个输入的号码都是 18 位,并且全部由数字组成。
输出格式:
在一行中输出失主的身份证号。题目保证输出唯一。
输入样例:
18328349823
10
130124198703030914
412901197609212008
450703198308160035
412928194606180028
413921194910290412
240902197104212813
371521198711123153
140113196511250117
622922200306127013
342520198912300017
输出样例:
371521198711123153
AC代码:
只需要判断后四位,利用stringstream对字符串拼接并判断,判断成功直接输出并结束程序即可。
#include "bits/stdc++.h"
using namespace std;
int main()
{
string phone;
cin >> phone;
int n;
cin >> n;
stringstream res;
for(int i = phone.length() - 4; i < phone.length(); i++){
res << phone[i];
}
for(int i = 0; i < n; i++)
{
string id;
cin >> id;
stringstream ss;
ss << id[7];
ss << id[8];
ss << id[4];
ss << id[id.length() - 1];
if(ss.str() == res.str()){
cout << id;
break;
}
}
return 0;
}