Contest3379 - 2024寒假集训 进阶训练赛 (五)题解

问题 A: 约瑟夫问题

题目描述

N个人围成一圈,从第一个人开始报数,数到M的人出圈;再由下一个人开始报数,数到M的人出圈;……输出依次出圈的人的编号。N,M由键盘输入。

输入

一行,包含两个正整数N,M。1<=N,M<=100。

输出

先输出一个空行,再依次出圈的人的编号。每个编号后都有一个空格。

样例输入 

8 5

样例输出 


5 2 8 7 1 4 6 3
#include <iostream>
#include <cmath>
#include <queue>
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<bits/stdc++.h> 
#include <vector>
 
using namespace std;
 
void josephus(int N, int M) {
    vector<int> people(N);
    for (int i = 0; i < N; ++i) {
        people[i] = i + 1;
    }
 
    cout << endl;
 
    int index = 0;
    while (N > 0) {
        index = (index + M - 1) % N;
        cout << people[index] << " ";
        people.erase(people.begin() + index);
        --N;
    }
}
 
int main() {
    int N, M;
    cin >> N >> M;
 
    josephus(N, M);
 
    return 0;
}

 

问题 B: 用筛法求质数

题目描述

用筛选法求出100以内的全部质数,并按每行五个数显示。

输入

输出

100以内的全部质数

提示

如果用c++的cout输出,在本题中可以使用setw(5)
setw(n)是在输出时分配了n个字符的输出宽度
如果用C的printf输出,可以用%5d

#include <iostream>
#include <cmath>
#include <queue>
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<bits/stdc++.h> 
#include <vector>
 
using namespace std;
 
void fun(int n) {
    bool isPrime[101];
    fill(isPrime, isPrime + 101, true);
 
    for (int p = 2; p * p <= n; p++) {
        if (isPrime[p]) {
            for (int i = p * p; i <= n; i += p) {
                isPrime[i] = false;
            }
        }
    }
 
    int count = 0;
    for (int p = 2; p <= n; p++) {
        if (isPrime[p]) {
            cout << setw(5) << p;
            count++;
            if (count % 5 == 0) {
                cout << endl;
            }
        }
    }
}
 
int main() {
    int limit = 100;
     
    fun(limit);
 
    return 0;
}

问题 C: 笨小猴

题目描述

笨小猴的词汇量很小,所以每次做英语选择题的时候都很头痛。经实验证明,用这种方法去选择选项的时候选对的几率非常大!

这种方法的具体描述如下:假设maxn是单词中出现次数最多的字母的出现次数,minn是单词中出现次数最少的字母的出现次数,如果maxn-minn是一个质数,那么笨小猴就认为这是一个Lucky Word,这样的单词很可能就是正确答案。

输入

    只有一行,是一个单词,其中只可能出现小写字母,且长度小于100。

输出

共两行,第一行是一个字符串,假如输入的单词是Lucky Word,那么输出“Lucky Word”,否则输出“No Answer”;

第二行是一个整数,如果输入单词是Lucky Word,输出maxn-minn的值,否则输出0。

样例输入 

error

样例输出 

Lucky Word
2

提示

【输入输出样例解释】

单词error中出现最多的字母r出现了3次,出现次数最少的字母出现1次,3-1=2,2是质数。

#include <iostream>
#include <cmath>
#include <queue>
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<bits/stdc++.h> 
#include <vector>
 
using namespace std;
 
bool isPrime(int n) {
    if (n <= 1) {
        return false;
    }
    for (int i = 2; i <= sqrt(n); i++) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}
 
int main() {
    string word;
    cin >> word;
 
    int frequency[26] = {0};
    for (char ch : word) {
        frequency[ch - 'a']++;
    }
 
    int maxn = 0, minn = word.length() + 1;
 
    for (int i = 0; i < 26; i++) {
        if (frequency[i] > 0) {
            maxn = max(maxn, frequency[i]);
            minn = min(minn, frequency[i]);
        }
    }
 
    if (isPrime(maxn - minn)) {
        cout << "Lucky Word" << endl;
        cout << maxn - minn << endl;
    } else {
        cout << "No Answer" << endl;
        cout << 0 << endl;
    }
 
    return 0;
}

 问题 D: 计算组合数

题目描述

计算组合数C(m, n)的值(n <= m <= 10)

输入

输入包含两个非负整数,用空格分隔

输出

输出仅一行,一个数即C(m,n)

样例输入 

4 1

样例输出 

4

提示

C(m,n) = m!/((m-n)! * n!)

 

#include <iostream>
#include <cmath>
#include <queue>
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<bits/stdc++.h> 
#include <vector>
 
using namespace std;
 
int fun(int num) {
    if (num == 0 || num == 1) {
        return 1;
    }
    return num * fun(num - 1);
}
 
int combination(int m, int n) {
    return fun(m) / (fun(m - n) * fun(n));
}
 
int main() {
    int m, n;
    cin >> m >> n;
 
    if (n <= m && m <= 10) {
        cout << combination(m, n) << endl;
    }
 
    return 0;
}

 问题 E: 整理药名

题目描述

医生在书写药品名的时候经常不注意大小写,格式比较混乱。现要求你写一个程序将医生书写混乱的药品名整理成统一规范的格式,即药品名的第一个字符如果是字母要大写,其他字母小写。如将ASPIRIN、aspirin整理成Aspirin。

输入

第一行一个数字n,表示有n个药品名要整理,n不超过100。
 

接下来n行,每行一个单词,长度不超过20,表示医生手书的药品名。药品名由字母、数字和-组成。

输出

n行,每行一个单词,对应输入的药品名的规范写法。

样例输入

4
AspiRin
cisapride
2-PENICILLIN
Cefradine-6

样例输出

Aspirin
Cisapride
2-penicillin
Cefradine-6

 

#include <iostream>
#include <cmath>
#include <queue>
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<bits/stdc++.h> 
#include <vector>
 
using namespace std;
 
string Drug(const string& drugName) {
    string standardized = drugName;
 
    if (!standardized.empty()) {
        standardized[0] = toupper(standardized[0]);  // 将第一个字符转换为大写
        for (size_t i = 1; i < standardized.length(); ++i) {
            standardized[i] = tolower(standardized[i]);  // 将其他字符转换为小写
        }
    }
 
    return standardized;
}
 
int main() {
    int n;
    cin >> n;
    cin.ignore();  // 忽略换行符
    for (int i = 0; i < n; ++i) {
        string drugName;
        getline(cin, drugName);
        string standardized = Drug(drugName);
        cout << standardized << endl;
    }
 
    return 0;
}

 问题 F: 矩阵转置

题目描述
输入一个n行m列的矩阵A,输出它的转置AT。
输入
第一行包含两个整数n和m,表示矩阵A的行数和列数(1≤n≤100,1≤m≤100)。
接下来n行,每行m个整数,表示矩阵A的元素。相邻两个整数之间用单个空格隔开,每个元素均在1~1000之间。

输出
m行,每行n个整数,为矩阵A的转置。相邻两个整数之间用单个空格隔开。
样例输入 
3 3
1 2 3
4 5 6
7 8 9
样例输出 
1 4 7
2 5 8
3 6 9

#include <iostream>
#include <cmath>
#include <queue>
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<bits/stdc++.h> 
#include <vector>
 
using namespace std;
 
int main() {
    int n, m;
    cin >> n >> m;
    vector<vector<int>> A(n, vector<int>(m));
    // 读取矩阵A
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            cin >> A[i][j];
        }
    }
    // 输出矩阵A的转置
    for (int j = 0; j < m; ++j) {
        for (int i = 0; i < n; ++i) {
            cout << A[i][j];
            if (i < n - 1) {
                cout << " ";
            }
        }
        cout << endl;
    }
 
    return 0;
}

问题 G: 素数判定优化

题目描述
判定n是否为一个素数,且n的最大值为1e18。显然如果用一般方法,则耗时高,因此需要一定的优化。
输入
输入数据有多组,每组数据占一行。
当输入0时结束。
0<=n<=1e18。
输出
如果输入的n为素数,则输出"OK",否则请输出“Sorry”,每组输出占一行。(实际输出均不带引号)
样例输入 
5
6
0
样例输出 
OK
Sorry
提示
规律:
    除2和3以外的所有素数,都可以写成6k-1或6k+1(k为整数),即当一个数在6的倍数的两侧时,它可能是素数,但当其不满足条件时,它一定不是素数

#include <iostream>
#include <cmath>
#include <queue>
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<bits/stdc++.h> 
#include <vector>
 
using namespace std;
 
bool isPrime(long long n) {
    if (n <= 1) {
        return false;
    }
    if (n == 2 || n == 3) {
        return true;
    }
    if (n % 2 == 0 || n % 3 == 0) {
        return false;
    }
 
    for (long long i = 5; i * i <= n; i += 6) {
        if (n % i == 0 || n % (i + 2) == 0) {
            return false;
        }
    }
 
    return true;
}
 
int main() {
    long long n;
    while (cin >> n && n != 0) {
        if (isPrime(n)) {
            cout << "OK" << endl;
        } else {
            cout << "Sorry" << endl;
        }
    }
 
    return 0;
}

问题 H: 水仙花数

题目描述
春天是鲜花的季节,水仙花就是其中最迷人的代表,数学上有个水仙花数,他是这样定义的:
“水仙花数”是指一个三位数,它的各位数字的立方和等于其本身,比如:153=1^3+5^3+3^3。
现在要求输出所有在m和n范围内的水仙花数。
输入
输入数据有多组,每组占一行,包括两个整数m和n(100<=m<=n<=999)。
输出
对于每个测试实例,要求输出所有在给定范围内的水仙花数,就是说,输出的水仙花数必须大于等于m,并且小于等于n,如果有多个,则要求从小到大排列在一行内输出,之间用一个空格隔开;
如果给定的范围内不存在水仙花数,则输出no;
每个测试实例的输出占一行。

样例输入 
100 120
样例输出 
no

#include <iostream>
#include <cmath>
#include <queue>
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<bits/stdc++.h> 
#include <vector>
 
using namespace std;
 
bool isN(int num) {
    int original = num;
    int digitSum = 0;
    while (num > 0) {
        int digit = num % 10;
        digitSum += pow(digit, 3);
        num /= 10;
    }
    return digitSum == original;
}
 
void fun(int m, int n) {
    bool found = false;
    for (int i = m; i <= n; ++i) {
        if (isN(i)) {
            cout << i << " ";
            found = true;
        }
    }
    if (!found) {
        cout << "no";
    }
    cout << endl;
}
 
int main() {
    int m, n;
    while (cin >> m >> n) {
        fun(m, n);
    }
 
    return 0;
}

问题 I: [蓝桥杯2022初赛] 选数异或

题目描述
给定一个长度为 n 的数列A1,A2,... , An 和一个非负整数 x。
给定 m 次查询, 每次询问能否从某个区间 [l, r] 中选择两个数使得他们的异或等于 x。

输入
输入第一行包含三个整数n,m,x。
第二行包含n个整数A1,A2,...,An。
接下来m行,每行两个整数l,r表示询问区间[l, r]。
20%的测试数据:1≤n,m≤100;
40%的测试数据:1≤n,m≤1000;
100%的测试数据:1≤n,m≤100000,0≤x,Ai<2^20,1≤l≤r≤n;

输出
对于每个询问, 如果该区间内存在两个数的异或为 x 则输出yes, 否则输出no。

样例输入 
4 4 1
1 2 3 4
1 4
1 2
2 3
3 3
样例输出 
yes
no
yes
no

#include <iostream>
#include <cmath>
#include <queue>
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<bits/stdc++.h> 
#include <vector>

using namespace std;

typedef long long ll;
const int N=1e5+5;
ll n,m,x;
int dp[N];    //a^b=x  a,b中早出现的数字位置
map<ll,int> mp;
int max(int a,int b){
  return a>b?a:b;
}
int main()
{
  ios_base::sync_with_stdio(0);
  cin.tie(0);  
  cin>>n>>m>>x;
  for(int i=1;i<=n;i++){
    ll data;
    cin>>data;
    dp[i]=max(dp[i-1],mp[data^x]);    //mp存放另一个数的位置
    mp[data]=i;
  }
  while(m--){
    int l,r;
    cin>>l>>r;
    if(dp[r]>=l) cout<<"yes\n";
    else cout<<"no\n";
  }
  return 0;
}

问题 J: [蓝桥杯2022初赛] 纸张尺寸

题目描述
在ISO 国际标准中定义了A0 纸张的大小为1189mm × 841mm。
将A0 纸沿长边对折后为A1 纸,大小为841mm × 594mm。
在对折的过程中长度直接取下整(实际裁剪时可能有损耗)。
将A1 纸沿长边对折后为A2 纸,依此类推。
输入纸张的名称,请输出纸张的大小。

输入
输入一行包含一个字符串表示纸张的名称。
该名称一定是A0、A1、A2、A3、A4、A5、A6、A7、A8、A9 之一。

输出
输出两行,每行包含一个整数,依次表示长边和短边的长度。

样例输入 
样例1:
A0

样例2:
A1
样例输出 
样例1:
1189
841

样例2:
841
594

#include <iostream>
#include <cmath>
#include <queue>
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<bits/stdc++.h> 
#include <vector>
 
using namespace std;
 
typedef long long ll;
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);  
    char ch;
    int n;
    cin>>ch>>n;
    int a=1189,b=841;
    for(int i=0;i<n;i++)
    {
        if(i%2==0)
        {
            a/=2;
        }
        else
            b/=2;
    }
    if(a>b)
        cout<<a<<endl<<b<<endl;
    else
        cout<<b<<endl<<a<<endl; 
    return 0;
}

问题 K: 添柴少年

题目描述
福葛又在暴揍纳兰珈!
因为小飞机连两个数的最小公倍数都不会求。
你能帮一帮他吗?
输入
两个正整数,每个整数在long long定义的C语言整数类型范围内。
输出
两个数的最小公倍数
样例输入 
7 9
样例输出 
63
提示
C语言中long long类型的整数输入输出对应的格式化字符串为“%lld”

#include <iostream>
#include <cmath>
#include <queue>
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<bits/stdc++.h> 
#include <vector>
 
using namespace std;
 
typedef long long ll;
 
 
// 辗转相除法计算最大公约数
long long gcd(long long a, long long b) {
    while (b != 0) {
        long long temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}
// 计算最小公倍数
long long lcm(long long a, long long b) {
    return (a * b) / gcd(a, b);
}
 
int main() {
    long long num1, num2;
    cin >> num1 >> num2;
 
    long long result = lcm(num1, num2);
 
    cout << result << endl;
 
    return 0;
}

问题 L: 你的就是我的,我的还是我的

题目描述
小F对小M说:
你的就是我的,我的还是我的。
初始时小M有 A AA 块饼干,小F有 B BB 块饼干。
小F会进行下面操作共 K KK 次:
如果小M还有饼干,就吃掉一块儿她的饼干
否则,如果小F还有饼干,就吃掉一块儿自己的饼干
如果两人都没有饼干了,就结束操作
输入
输入描述
输入包括一行空格隔开的三个正整数 A B K
0 ≤ A ≤ 1 0 12 0leq A leq 10^{12}0≤A≤10 
12
 
0 ≤ B ≤ 1 0 12 0leq B leq 10^{12}0≤B≤10 
12
 
0 ≤ K ≤ 1 0 12 0leq K leq 10^{12}0≤K≤10 
12
 
输出
输出一行空格隔开的两个字符串,分别代表小M和小F剩下的饼干数。
样例输入
2 3 3
样例输出
0 2

#include <iostream>
#include <cmath>
#include <queue>
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<bits/stdc++.h> 
#include <vector>

using namespace std;

typedef long long ll;
int main() {
    long long A, B, K;
    cin >> A >> B >> K;
    if(A==0)
    {
        if(B<=K)
        {
            B=0;
        }
        else
            B-=K;
    }
    else if(A>0)
    {
        if(A>=K)
        {
            A-=K;
            K=0;
        }
        else
        {
            K-=A;
            A=0;
            if(B<=K)
            {
                B=0;
            }
            else
                B-=K;
        }
    }
 
    cout << A << " " << B << endl;
 
    return 0;
}

问题 M: 下一个素数

题目描述
小T说:请找到不小于T的最小的素数
素数是除了1和自身外不能被其他整数整除的大于1的正整数
输入
输入包括一行一个正整数T
2<=T<=10^5
输出
输出一行一个正整数,代表不小于T的最小素数
样例输入 复制
20
样例输出 复制
23

#include <iostream>
#include <cmath>
#include <queue>
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<bits/stdc++.h> 
#include <vector>
 
using namespace std;
 
typedef long long ll;
bool isPrime(int n) {
    if (n <= 1) {
        return false;
    }
    for (int i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}
 
int findNextPrime(int T) {
    while (!isPrime(T)) {
        T++;
    }
    return T;
}
 
int main() {
    int T;
    cin >> T;
 
    int result = findNextPrime(T);
 
    cout << result << endl;
 
    return 0;
}

问题 N: 三角形牧场

题目描述

和所有人一样,奶牛喜欢变化。它们正在设想新造型的牧场。奶牛建筑师)oh想建造围有漂亮白色栅栏的三角形牧场。 他拥有块木板,每块的长度Ai都是整数。 他想要选三块木板,使得它们的长度能够构成一个三角形,请问有多少种选择方法呢?

输入

第一行,

一个整数,代表n(3≤n≤2×103) 第二行,n个整数,代表Ai(1≤Ai≤103)输出 输出一个整数,代表方案数

样例输入

 5

1 2 3 4 3

样例输出

 5

提示

样例解释:共五种方案: (1,3,3),(2,3,3),(2,3,4)有两个,(3,3,4)

#include <iostream>
#include <cmath>
#include <queue>
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<bits/stdc++.h> 
#include <vector>
 
using namespace std;
 
typedef long long ll;
 
int countTriangleBoards( vector<int>& boards) {
    int count = 0;
    int n = boards.size();
 
    // 对木板长度排序
    sort(boards.begin(), boards.end());
 
    // 遍历所有可能的两元组
    for (int i = 0; i < n - 2; ++i) {
        int k = i + 2;
 
        for (int j = i + 1; j < n - 1; ++j) {
            // 寻找第三个木板的位置
            while (k < n && boards[i] + boards[j] > boards[k]) {
                k++;
            }
 
            // 计算符合条件的三元组数量
            count += max(0, k - j - 1);
        }
    }
 
    return count;
}
 
int main() {
    int n;
    cin >> n;
 
    vector<int> boards(n);
 
    for (int i = 0; i < n; ++i) {
        cin >> boards[i];
    }
 
    int result = countTriangleBoards(boards);
 
    cout << result << endl;
 
    return 0;
}

问题 Q: 打怪兽version-2

题目描述 有一只怪兽的血量为H 你需要在N回合之内杀死它 第i个回合你可以对其造成 点伤害 问是否可以杀死怪兽(其血量小于等于0即为死亡) 可以输出Yes 否则输出No

输入

H N .......

1 <= H <= 1e9 1 <= N <= 1e5 1 <= <=1e4

输出

问是否可以杀死怪兽(其血量小于等于0即为死亡) 可以输出Yes 否则输出No

样例输入

10 3 4 5 6

样例输出

Yes

#include <iostream>
#include <cmath>
#include <queue>
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<bits/stdc++.h> 
#include <vector>
 
using namespace std;
 
typedef long long ll;
 
int main() {
    long long H, N;
    cin >> H >> N;
 
    vector<long long> damage(N);
 
    for (int i = 0; i < N; ++i) {
        cin >> damage[i];
    }
 
    long long totalDamage = 0;
 
    for (int i = 0; i < N; ++i) {
        totalDamage += damage[i];
        if (totalDamage >= H) {
            cout << "Yes" << endl;
            return 0;
        }
    }
 
    cout << "No" << endl;
 
    return 0;
}

  • 18
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值