第1讲 C/C++的应用训练

1.U307221 奇偶数

题目描述

输入一个正整数n,如果n是奇数,那么输出"Odd Number";如果n是偶数,那么输出"Even Number"。

输入格式

一个正整数n(1≤n≤100000)。

输出格式

按题意输出"Odd Number"或"Even Number"。

输入输出样例

输入 #1

5

输出 #1

Odd Number

输入 #2

10

输出 #2

Even Number

参考代码:

#include<bits/stdc++.h>

using namespace std;

int main() {

    int n;

    cin>>n;

   if(n%2==0){

        cout<<"Even Number";

   } else{

        cout<<"Odd Number";

   }

   return 0;

}

2.U307243 输出整数

题目描述:输入一个正整数n,输出n行,其中第i行为从1到i的所有整数。

输入格式

一个正整数n(1≤n≤100000)。

输出格式

共n行,其中第i行为从1到i的所有正整数。整数间用一个空格隔开,行末不允许有多余的空格。

输入输出样例

输入 #1

3

输出 #1

1

1 2

1 2 3

输入 #2

4

输出 #2

1

1 2

1 2 3

1 2 3 4

参考代码:

#include <stdio.h>

int main() {

    int n;

    // 输入正整数n

    scanf("%d", &n);

    // 外层循环控制行数

    for (int i = 1; i <= n; i++) {

        // 内层循环输出从1到i的数字

        for (int j = 1; j <= i; j++) {

            printf("%d ", j); // 每个数字后跟一个空格

        }

        printf("\n"); // 每行结束后换行

    }

    return 0;

}

3.U307315 与2无关的数

题目描述

一个正整数,如果它能被2整除,或者它的十进制表示中某个位数上的数字为2,则称其为与2相关的数。求所有小于等于N的与2无关的正整数的和。 例如:N = 8,<= 8与2无关的数包括:1 3 5 7,和为:16。

输入格式

一行,一个n, 2<=n<=100。

输出格式

一行,输出一个整数,表示答案。

输入输出样例

输入 #1

8

输出 #1

16

参考代码:

#include <stdio.h>

int main() {

   int N;

   scanf("%d", &N);

   long long sum = 0; // 可能和较大,用long long

   for (int i = 1; i <= N; i++) {

        if (i % 2 == 0) continue; // 能被2整除,相关,跳过

        // 检查各位是否有2

        int temp = i;

        int hasTwo = 0;

        while (temp > 0) {

              if (temp % 10 == 2) {

                   hasTwo = 1;

                   break;

              }

              temp /= 10;

        }

        if (hasTwo) continue;

        sum += i;

   }

   printf("%lld\n", sum);

   return 0;

}

第2讲 穷举算法、迭代算法和入门模拟

1.U413399整数出现次数

给定个正整数,按从小到大的顺序输出每个整数的出现次数。

输入描述

第一行一个正整数n(1<=n<=1000);

第二行为用空格隔开的n个正整数(每个正整数的大小均不超过100)。

输出描述

输出若干行,每行输出一个整数和它的出现次数,中间用空格隔开。

样例1

输入

4

3 1 5 3

输出

1 1

3 2

5 1

解释

1出现了1次,3出现了2次,5出现了1次

参考答案:

#include <cstdio>

int main () {

   int hashTable[101] = {0};

    int n, x;

    scanf("%d", &n);

    for (int i = 0; i < n; i++) {

        scanf("%d", &x);

        hashTable[x]++;

    }

    for (int i = 1; i <= 100; i++) {

        if (hashTable[i]) {

            printf("%d %d\n", i, hashTable[i]);

        }

    }

    return 0;

}

3.U413390日期先后

给定两个日期DAY1和DAY2,判断DAY1是否在DAY2之前。

输入描述

前两行分别为日期DAY1和DAY2(格式为YYYY-MM-DD,范围为1900-01-01≤DAY≤2199-12-31),数据保证一定合法。

输出描述

如果DAY1在DAY2之前,那么输出YES,否则输出NO。

样例1

输入

2021-05-01

2021-05-07

输出

YES

参考答案:

#include <cstdio>

int isBefore(int year1, int month1, int day1, int year2, int month2, int day2) {

    if (year1 != year2) {

        return year1 < year2;

    }

    if (month1 != month2) {

        return month1 < month2;

    }

    return day1 < day2;

}

int main() {

    int year1, month1, day1;

    int year2, month2, day2;

    scanf("%d-%d-%d", &year1, &month1, &day1);

    scanf("%d-%d-%d", &year2, &month2, &day2);

    printf(isBefore(year1, month1, day1, year2, month2, day2) ? "YES" : "NO");

    return 0;

}

4.U415278计算输入数据的和与乘积

题目描述

输入一个整型数据,计算这个数据里面所以数字的和值与乘积

输入

一个整型数字(不超过十位)

输出

这个数字里所有数字的和值乘积空格分开

样例输入

1234

样例输出

10 24

参考答案:

#include<bits/stdc++.h>

using namespace std;

int main ()

   char a[11];

   int i,sum =0,ave=1,temp;

    cin>>a;

   for(i=0;i<strlen(a);i++)

   {

        temp=a[i]-'0';//字符转换为单个数字   

        sum+=temp;    

        ave*=temp;

   }   

   cout<<sum<<" "<<ave;

   return 0;

}

算法初步

1 散列算法

1.U415270统计同成绩学生

题目描述

本题要求读入N名学生的成绩,然后将获得某一给定分数的学生人数输出。

输入格式

第一行给出不超过105的正整数N,即学生总人数;第二行给出N名学生的百分制整数成绩,中间以空格分隔;第三行给出要查询的分数个数K(不超过N的正整数),随后是K个分数,中间以空格分隔。

输出格式

在一行中按查询顺序给出得分等于指定分数的学生人数,中间以空格分隔,但行末不得有多余空格。

输入样例

10

60 75 90 55 75 99 82 90 75 50

3 75 90 88

输出样例

3 2 0

参考答案

#include <iostream>

using namespace std;

int hashTable[110] = {0}; //记录每个分数出现的次数

int main(){

   int n, score, k;

   cin>>n; //学生数

   for(int i=0;i<n; i++){

        scanf("%d",&score);//分数

        hashTable[score]++;//分数score出现的次数加1

   }

   cin>>k; //查询次数

   for (int i=0;i< k; i++){

        cin>>score;

        cout<<hashTable[score];//查询分数score出现的次数

        if(i<k-1){

              cout<<" ";//前K-1个结果后面输出空格

        }

   }

   return 0;

}

2.U415273集合求交

给定一个包含n个正整数的集合S1,再给定一个包含m个正整数的集合S2,求两个集合的交集。

输入描述

第一行两个正整数n、m(1<=n,m<=104),分别表示集合S1和S2的成员数;

第二行按升序给出S1的n个正整数成员(每个正整数的大小均不超过104,且互不相同)。

第三行按升序给出S2的m个正整数成员(每个正整数的大小均不超过104,且互不相同)。

输出描述

按升序输出集合S1和S2的交集。结果之间用空格隔开,行末不允许有多余的空格。

输入

5 4

1 2 5 6 8

2 4 6 7

输出

2 6

参考答案:

#include <iostream>

using namespace std;

int main(){

    int hashTable[10001] = {0};

    int n, m, x;

    cin>>n>>m;

    for (int i = 0; i < n; i++) {

        cin>>x;

        hashTable[x] = 1;

    }

    int isFirst = 1;

    for (int i = 0; i < m; i++) {

         cin>>x;

         if (hashTable[x]) {

           if(!isFirst){

              cout<<" ";

            }

            cout<<x;

            isFirst = 0; 

        }

    }

    return 0;

}

3.U417371集合求差

给定一个包含n个正整数的集合S1,再给定一个包含m个正整数的集合S2,求两个集合的差集,即S1−S2。

输入描述

第一行两个正整数n、m(1≤n≤104,1≤m≤104),分别表示集合S1和S2的成员数;

第二行按升序给出S1的n个正整数成员(每个正整数的大小均不超过103,且可能重复)。

第三行按升序给出S2的m个正整数成员(每个正整数的大小均不超过103,且可能重复)。

输出描述

按升序输出集合S1和S2的差集。结果之间用空格隔开,行末不允许有多余的空格。

样例1

输入

5 2

2 2 2 6 8

2 6

输出

2 2 8

解释

集合S1中有3个2,集合S2中有1个2,因此作差后还剩2个2;

集合S1中有1个6,集合S2中有1个6,因此作差后还剩0个6;

集合S1中有1个8,集合S2中有0个8,因此作差后还剩1个8;

因此差集为{2,2,8}

参考答案:

#include <iostream>

using namespace std;

int main () {

   int hashTable[1001] = {0};

    int n, m, x;

    cin>>n>>m;

    for (int i = 0; i < n; i++) {

        cin>>x;

        hashTable[x]++;

    }

    for (int i = 0; i < m; i++) {

         cin>>x;

        hashTable[x]--;

    }

    int isFirst = 1;

    for (int i = 1; i < 1001; i++) {

        for (int j = 0; j < hashTable[i]; j++) {

            if(!isFirst){

              cout<<" ";

            }

            cout<<i;

            isFirst = 0;

        }

    }

    return 0;

}

4.U413409单词倒序

给定一堆用空格隔开的英文单词,输出这些英文单词的倒序(单词内部保持原序)。

输入描述

一堆英文单词,每个单词不超过10个字符,且仅由大小写字母组成;每两个单词之间用一个空格隔开,整个字符串的长度不超过1000。

输出描述

输出英文单词的倒序,单词之间仍然是一个空格隔开,行末不允许有多余的空格。

样例1

输入

Hao Hao Xue Xi

输出

Xi Xue Hao Hao

参考答案

#include <cstdio>

int main() {

   char str[1000][11], num = 0;  

    while (scanf("%s", str[num]) != EOF) {

        num++;

    }

    for (int i = num - 1; i >= 0; i--) {

        printf("%s", str[i]);

        if (i > 0) {

            printf(" ");

        }

    }

    return 0;

}

3.2 递归算法

1.吓得我抱起了我的小鲤鱼

在这个定义下:

当n=0时,整个句子是“吓得我抱起了我的小鲤鱼”;

当n=1时,整个句子是“吓得我抱起了抱着我的小鲤鱼的我”;

当n=2时,整个句子是“吓得我抱起了抱着抱着我的小鲤鱼的我的我”;

当n=3时,整个句子是“吓得我抱起了抱着抱着抱着我的小鲤鱼的我的我的我”;

请根据n的大小,输出对应的句子。

输入描述

一个整数n(1<=n<=100),含义如题意所示。

输出描述

对应的表情中的完整句子。

样例1

输入

0

输出

吓得我抱起了我的小鲤鱼

样例2

输入

3

输出

吓得我抱起了抱着抱着抱着我的小鲤鱼的我的我的我

参考答案:

#include <iostream>

using namespace std;

void print(int n) {

    if (n == 0) {

        cout<<"我的小鲤鱼";

    } else {

        cout<<"抱着";

        print(n - 1);

        cout<<"的我";

    }

}

int main() {

    int n;

    cin>>n;

    cout<<"吓得我抱起了";

    print(n);

    return 0;

}

2.从前有座山

很多人都知道从前有座山的故事,它是这样的:

从前有座山,山上有座庙

庙里有一个老和尚和一个小和尚

睡前老和尚给小和尚讲故事:

……

然后老和尚和小和尚就睡觉啦

对本题来说,整个故事是下面的严格定义。

当n=0时,故事A(n)是

讲你妹的故事啊!快点去睡觉!!!

当n>0时,故事A(n)是

从前有座山,山上有座庙

庙里有一个老和尚和一个小和尚

睡前老和尚给小和尚讲故事:

A(n-1)

然后老和尚和小和尚就睡觉啦

请根据n的大小,输出对应的故事。

输入描述

一个整数n(1≤n≤100),含义如题意所示。

输出描述

故事A(n)。

样例1

输入

0

输出

讲你妹的故事啊!快点去睡觉!!!

样例2

输入

1

输出

从前有座山,山上有座庙

庙里有一个老和尚和一个小和尚

睡前老和尚给小和尚讲故事:

讲你妹的故事啊!快点去睡觉!!!

然后老和尚和小和尚就睡觉啦

样例3

输入

2

输出

从前有座山,山上有座庙

庙里有一个老和尚和一个小和尚

睡前老和尚给小和尚讲故事:

从前有座山,山上有座庙

庙里有一个老和尚和一个小和尚

睡前老和尚给小和尚讲故事:

讲你妹的故事啊!快点去睡觉!!!

然后老和尚和小和尚就睡觉啦

然后老和尚和小和尚就睡觉啦

参考答案:

#include <iostream>

using namespace std;

void print(int n) {

    if (n == 0) {

        cout<<"讲你妹的故事啊!快点去睡觉!!!\n";

    } else {

        cout<<"从前有座山,山上有座庙\n";

        cout<<"庙里有一个老和尚和一个小和尚\n";

        cout<<"睡前老和尚给小和尚讲故事:\n";

        print(n - 1);

        cout<<"然后老和尚和小和尚就睡觉啦\n";

    }

}

int main() {

    int n;

    cin>>n;

    print(n);

    return 0;

}

4.U417383猴子吃桃的问题

题目描述

猴子吃桃问题。猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。 第二天早上又将剩下的桃子吃掉一半,又多吃一个。以后每天早上都吃了前一天剩下的一半零一个。 到第N天早上想再吃时,见只剩下一个桃子了。求第一天共摘多少桃子。

输入

N

输出

桃子总数

样例输入

10

样例输出

1534

参考答案

#include<stdio.h>

int fruit(int n){

   if(n==1) return 1;

   return (fruit(n-1)+1)*2;

}

int main(){

   int N;

   scanf("%d",&N);

   printf("%d",fruit(N));

   return 0;

}

3.U417393莲花池

题目描述

有个莲花池里起初有一只莲花,每过一天莲花的数量就会翻一倍。假设莲花永远不凋谢,30天的时候莲花池全部长满了莲花, 请问第n(5<=n<=30)天的莲花占莲花池的几分之几.

输入格式

n

输出格式

百分比,保留8位小数

输入

23

输出

0.00781250

参考答案:

#include<stdio.h>

int fn(int a);

int main(){

   long long aa,bb;

   double cc;

   int n;

   scanf("%d",&n);

   aa = fn(30);

   bb = fn(n);

   cc = (double)bb/aa;

   printf("%.8f\n", cc);

   return 0;

}

int fn(int n){

   if(n == 1){

        return 1;

   }

   else{

        return  fn(n-1)*2;

   }

}

3.3 贪心算法

1.U421343最优装箱

题目描述

有n个箱子需要装上一艘轮船,已知第i个箱子的重量为wi,轮船的载重为W。问在不超过轮船载重的前提下,最多能把多少个箱子装上轮船。

输入描述

第一行两个正整数n、W(1≤n≤105、1≤W≤107),分别表示箱子个数和轮船载重。

第二行n个正整数wi(1≤wi≤107),表示n个箱子的重量。

输出描述

输出两个整数,分别表示能装上轮船的箱子个数和总重量,用空格隔开。

样例1

输入

5 11

7 2 9 1 11

输出

3 10

样例1

输入

4 80

54 89 45 12

输出

2 57

样例1解释

能将重量分别为7、2、1的箱子装上轮船(此时箱子个数最多),总重量为10。

样例2解释

能将重量分别为45、12的箱子装上轮船(此时箱子个数最多),总重量为57。(注意,优先把重量值小的箱子搬上轮船)

参考答案:

#include <bits/stdc++.h>

//#include <algorithm>

using namespace std;

int main() {

   int a[100001];

    int n, maxW;

    cin>>n>>maxW;

    for (int i = 0; i < n; i++) {

        cin>>a[i];

    }

    sort(a, a + n);

    int num = 0, sum = 0;

    for (int i = 0; i < n; i++) {

        if (sum + a[i] <= maxW) {

            num++;

            sum += a[i];

        } else {

            break;

        }

    }

    cout<<num<<" "<<sum ;

    return 0;

}

2.U422123最大组合整数

题目描述

现有0~9中各个数的个数,将它们组合成一个整数,求能组合出的最大整数。

输入描述

在一行中依次给出0~9中各个数的个数(所有个数均在0~100之间)。数据保证至少有一个数的个数大于0。

输出描述

输出一个整数,表示能组合出的最大整数。

样例1

输入

1 0 2 0 0 0 0 0 0 1

输出

9220

解释

存在1个0、2个2、1个9,因此能组合出的最大整数是9220

参考答案:

#include <bits/stdc++.h>

//#include <algorithm>

using namespace std;

int main() {

   int cnt[10];

    for (int i = 0; i < 10; i++) {

        cin>>cnt[i];

    }

    int isZero = 1;

    for (int i = 9; i >= 0; i--) {

        if (i > 0 && cnt[i] > 0) {

            isZero = 0;

        }

        if (!isZero) {

            for (int j = 0; j < cnt[i]; j++) {

               cout<<i;

            }

        }

    }

    if (isZero) {

       cout<<"0";

    }

    return 0;

}

3.U422129同学的等待

题目描述

同学们下课后去食堂,每个人都需要一段时间去点菜。

然而,某些同学点菜时间太长了。同学们对于等待很烦躁:他们希望,能尽量少的花时间等待。

(同学数<=100000),(0<=点菜耗时<=10000)

他们希望在点菜时,能排成一个次序,使得总等待时间最短(即不包括点菜人的其他所有人的等待时间)。

输入

第一行是一个数字n,表示同学的个数

接下来n个数,表示点菜的耗时

输出

一个数,表示总等待时间。

样例输入

6

9 1 3 5 4 2

样例输出

35

参考答案

#include <bits/stdc++.h>

//#include <algorithm>

using namespace std;

int main() {

   int a[100001];

    int n;

    cin>>n;

    for(int i = 1;i<=n;i++)

        scanf("%d",&a[i]);

    sort(a+1,a+n+1);

    long long sum = 0;

    for(int i = 1; i<=n;i++) {

        sum += a[i]*(n-i);

    }

    cout<<sum<<endl;

    return 0;

}

3.4 二分算法

1.U423603寻找指定元素II

在一个严格递减序列A中寻找一个指定元素x,如果能找到,那么输出它的下标;如果不能找到,那么输出−1。

注:使用二分法实现。

输入描述

第一行为两个正整数n(1≤n≤105)、x(1≤x≤106),分别表示严格递减序列A中元素的个数、需要寻找的元素;

第二行按顺序给出n个严格递减的正整数,表示序列A中的元素(1≤每个元素≤106)。假设序列的下标从0开始。

输出描述

如果能找到x,那么输出它的下标;否则输出−1。

样例1

输入

5 3

8 5 3 2 1

输出

2

样例2

输入

5 6

8 5 3 2 1

输出

-1

参考答案:

#include <iostream>

using namespace  std;

const int MAXN = 100000;

int n, a[MAXN], target;

int binarySearch() {

    int l = 0, r = n - 1;

    while (l <= r) {

        int mid = (l+r) / 2;

        if (a[mid] == target) {

            return mid;

        } else if (a[mid] > target) {

            l = mid + 1;

        } else if (a[mid] < target) {

            r = mid - 1;

        }

    }

    return -1;

}

int main() {

    cin>>n>>target;

    for (int i = 0; i < n; i++) {

        cin>>a[i];

    }

    cout<<binarySearch();

    return 0;

}

3.U425603日期排序

有一些日期,日期格式为“MM/DD/YYYY”。编程将其按日期大小排列。

输入

输出

样例输入

05/12/1999

10/21/2003

10/22/2003

02/12/2004

11/30/2005

12/31/2005

样例输出

05/12/1999

10/21/2003

10/22/2003

02/12/2004

11/30/2005

12/31/2005

参考答案:

#include<bits/stdc++.h>

using namespace std;

struct date{

    int year,month,day;

}dd[100];

int cmp(date a,date b){

    if(a.year!=b.year)

        return a.year<b.year;

    else if(a.month!=b.month)

        return a.month<b.month;

    else

        return a.day<b.day;     

}

int main(){

    int i=0;

    while(scanf("%d/%d/%d",&dd[i].month,&dd[i].day,&dd[i].year)!=EOF){

        i++;

    }

    sort(dd,dd+i,cmp);

    for(int j=0;j<i;j++)

        printf("%02d/%02d/%04d\n",dd[j].month,dd[j].day,dd[j].year);

    return 0;

 }

4.U680528首字母大写

给定一堆用空格隔开的英文单词,将每个单词的首字母改为大写后输出。

输入描述

一堆英文单词,每个单词不超过10个字符,且仅由小写字母组成;每两个单词之间用一个空格隔开,整个字符串的长度不超过1000。

输出描述

输出每个单词首字母大写后的结果,单词之间仍然是一个空格隔开,行末不允许有多余的空格。

样例1

输入

good good study

输出

Good Good Study

参考答案:

#include <bits/stdc++.h>

using namespace std;

int main() {

   int i=0;

   char str[1000];

    while (scanf("%s", str) != EOF) {    

       if(i!=0) printf(" "); 

        int len = strlen(str);

        printf("%c", str[0] -32);

        for (int j = 1; j < len; j++) {

            printf("%c", str[j]);

        }

        i=1;

    }

    return 0;

}

  数学问题

1.U425809组合数

给定两个非负整数n和m,求Cnm的值。

输入描述

两个非负整数n、m(1≤n≤50,0≤m≤50,m≤n),含义如题意所述。

输出描述

输出一个整数,表示Cnm的值。

样例1

输入

6 2

输出

15

解释

C62=6*5/2*1=15

参考答案:

#include <cstdio>

typedef long long LL;

LL C(LL n, LL m) {

    LL ans = 1;

    for (LL i = 1; i <= m; i++) {

        ans = ans * (n - m + i) / i;

    }

    return ans;

}

int main() {

    LL n, m;

    scanf("%lld%lld", &n, &m);

    printf("%lld", C(n, m));

    return 0;

}

2.U428209 左小数

给定由n个正整数组成的序列,问在序列中有多少个数,满足在它左边的所有数都比它小。

输入描述

第一行一个整数n(1≤n≤105),表示序列中正整数的个数;

第二行按顺序给出序列中的n个正整数(每个正整数均不超过106且互不相同)。

输出描述

输出满足条件的整数个数。

样例1

输入

4

1 3 2 4

输出

3

解释

1的左边没有数,满足条件;

3的左边所有数都比3小,满足条件;

2的左边存在不小于2的数,不满足条件;

4的左边所有数都比4小,满足条件;

因此共3个数满足条件。

参考答案:

#include<bits/stdc++.h>

using namespace std;

int main() {

    int n, x, leftMax = 0;

    scanf("%d", &n);

    int result = 0;

    for (int i = 0; i < n; i++) {

        cin>>x;

        if (x > leftMax) {

            result++;

        }

        leftMax = max(leftMax, x);

    }

    cout<<result;

    return 0;

}

3.U427935前缀和

给定由n个正整数组成的序列,接下来给出k个查询,每个查询指定一个正整数m,计算序列前m个正整数之和。

输入描述

第一行一个整数n(1≤n≤104),表示序列中正整数的个数;

第二行按顺序给出序列中的n个正整数(每个正整数均不超过104);

第三行一个整数k(1≤k≤104),表示查询的个数;

接下来k行,每行一个整数m(1≤m≤n),表示需要计算序列前m个正整数之和。

输出描述

输出k行,每行一个查询结果,表示序列前m个正整数之和。

样例1

输入

5

2 8 5 1 3

3

1

3

5

输出

2

15

19

解释

前1个正整数之和是2;

前3个正整数之和是2+8+5=15;

前5个正整数之和是2+8+5+1+3=19。

参考答案:

#include<bits/stdc++.h>

using namespace std;

int main() {

   int n, a[10000];

   int sum[10000] = {0};

    cin>>n;

    for (int i = 0; i < n; i++) {

        cin>>a[i];

        if (i == 0) {

            sum[i] = a[i];

        } else {

            sum[i] = sum[i - 1] + a[i];

        }

    }

    int k, m;

    cin>>k;

    for (int i = 0; i < k; i++) {

       cin>>m;

       cout<<sum[m - 1]<<endl;

    }

    return 0;

4.B3866 [GESP202309 二级] 数字黑洞

题目描述

给定一个三位数,要求各位不能相同。例如,352是符合要求的,112是不符合要求的。将这个三位数的三个数字重新排列,得到的最大的数,减去得到的最小的数,形成一个新的三位数。对这个新的三位数可以重复上述过程。神奇的是,最终一定会得到495!

试试看,重新排列352,得到的最大数为532,最小数为235,它们的差是297;变换297,得到972−279=693;变换693,963−369=594;变换594,954−459=495。因此,经过4次变换得到了495。

现在,输入的三位数,你能通过编程得出,这个三位数经过多少次变换能够得到495吗?

输入格式

输入一行,包含一个符合要求的三位数N。

输出格式

输出一行,包含一个整数C,表示经过C次变换得到495。

输入输出样例

输入 #1

352

输出 #1

4

参考答案:

#include <cstdio>

#include <algorithm>

using namespace std;

bool cmp(int a,int b) { //递减排序 cmp

   return a > b;

}

//将 n的每一位存到num数组中

void to_array(int n, int num[]) {

    for(int i=0;i<3;i++){

   num[i] = n % 10;

   n /= 10;

    }

}

//将num数组转换为数字

int to_number(int num[]) { 

     int sum = 0;

     for(int i =0; i< 3; i++) {

   sum = sum * 10+ num[i] ;

     }

     return sum;

}

int main() {

   //MIN和MAX分别表示递增排序和递减排序后得到的最小值和最大值

   int n, MIN, MAX,result=0;

   scanf("%d", &n) ;

   int num[4] ;

   while (1) {

        to_array(n, num) ;

        //将n转换为数组

        sort(num, num + 3) ;

        //对 num数组中元素从小到大排序

        MIN = to_number (num); //获取最小值

        sort(num, num + 3,cmp) ;

        //对num数组中元素从大到小排序

        MAX = to_number (num) ;

        //获取最大值

        n = MAX- MIN; //得到下一个数

        result++;

        if(n==495) break;// 下一个数如果是495则退出

   }

   printf("%d",result);

   return 0;

}

C++ STL标准库

1.U429878数列排序

将一个有n(n<=100000)个元素组成的正整数序列{K1,K2,K3,K4,K5,......}重新排列成一个新的序列。新序列中,比K1小的数都在K1的前面(左面),比K1大的数都在K1的后面(右面)。

输入

输入有两行,第一行为n表示正整数个数,第二行是n个正整数。

输出

输出一行,按要求进行排序的结果。

样例输入

10

60 88 90 10 22 55 40 70 30 150

样例输出

30 40 55 22 10 60 88 90 70 150

参考答案

#include<iostream>

#include<vector>

using namespace std;

int main(){

   vector<int>  xyz;

   int n,k1,temp;

   cin>>n;

   cin>>k1;

   xyz.push_back(k1);

   for(int i=0;i<n-1;i++){

        cin>>temp;

        if(temp<k1){

              xyz.insert(xyz.begin(),temp);

        }else{

              xyz.push_back(temp);

        }   

   }

   vector<int>::iterator iiiiiii;

   for(iiiiiii=xyz.begin();iiiiiii!=xyz.end();iiiiiii++){

        cout<<*iiiiiii<<" ";

   }         

}

2.U429875 :C语言网:1605: 蓝桥杯算法训练VIP-阿尔法乘积

题目描述

 计算一个整数的阿尔法乘积。对于一个整数x来说,它的阿尔法乘积是这样来计算的:如果x是一个个位数,那么它的阿尔法乘积就是它本身;否则的话,x的阿尔法乘积就等于它的各位非0的数字相乘所得到的那个整数的阿尔法乘积。例如:4018224312的阿尔法乘积等于8,它是按照以下的步骤来计算的:

4018224312  →  4*1*8*2*2*4*3*1*2  →  3072  →  3*7*2  →  42  →  4*2  →  8

编写一个程序,输入一个正整数(该整数不会超过6,000,000,000),输出它的阿尔法乘积。

输入

输入只有一行,即一个正整数。 

输出

输出相应的阿尔法乘积。 

样例输入

4018224312

样例输出

8

参考答案

#include <iostream>

#include <vector>

using namespace std;

int main(){

    vector<int>a;

    long long  num;

    cin >> num;

    for(; num > 0 ; num /= 10){   

        a.push_back(num % 10);

    }

    while(a.size() != 1){

        long long  sum = 1;

        for(int i = 0; i < a.size(); i++){

            if(a[i] == 0){

                continue;

            }else{

                sum *= a[i];

            }

        }

        a.clear();

        for(; sum > 0 ; sum /= 10){

            a.push_back(sum % 10);

        }

    }

    cout << a[0] << endl;

    return 0;

}

3.U430127 :C语言网:[2065]{A} + {B}

题目描述

给你两个集合,要求{A} + {B}.

注:同一个集合中不会有两个相同的元素.

输入

每组输入数据分为三行,第一行有两个数字n,m(0<n,m<=10000),

分别表示集合A和集合B的元素个数.后两行分别表示集合A和集合B.    

每个元素为不超出int范围的整数,每个元素之间有一个空格隔开.

输出

针对每组数据输出一行数据,表示合并后的集合,要求从小到大输出,   

每个元素之间有一个空格隔开.

样例输入

1 2

1

2 3

1 2

1

1 2

样例输出

1 2 3

1 2

参考答案:

#include <iostream>

#include <set>

using namespace std;

int main()

{

   set<int> myset;

   int n,m,temp;

   while(cin>>n>>m){

       while(n--&&cin>>temp){

           myset.insert(temp);

       }

       while(m--&&cin>>temp){

           myset.insert(temp);

       }

      for(set<int>::iterator i=myset.begin();i!=myset.end();i++){

           cout<<*i<<" ";

       }

       myset.clear();

       cout<<endl;

   }

   return 0;

}

4.U432033统计输入的不同单词个数

题目描述

输入若干个单词,输出不用单词个数

输入

若干行,第一行为n,表示输入单词的个数。

接下来为n行,每一行一个单词。

输出

一个整数,表示不用单词个数

样例输入

8

he

you

student

you

she

he

you

student

样例输出

4

参考答案:

#include <iostream>

#include<set>

#include<string>

using namespace std;

int main() {

    set<string> s;

    string str;

    int n;

    cin>>n;

    while(n--){

        cin >> str;

        s.insert(str);

    }

    cout << s.size();

    return 0;

}

5.P15799 [GESP202603 五级] 找数

题目描述

给定一个包含n个互不相同的正整数的数组A与一个包含m个互不相同的正整数的数组B,请你帮忙计算有多少个数在数组A与数组B中均出现。

输入格式

第一行包含两个整数n,m。

第二行包含n个正整数a1,a2,⋯,an表示数组A。

第三行包含m个正整数b1,b2,⋯,bm表示数组B。

输出格式

输出一个整数,表示在数组 A与数组B中均出现的数的个数。

输入输出样例

输入 #1复制

3 5

4 2 3

3 1 5 4 6

输出 #1复制

2

说明/提示

样例解释

样例1中,4、3在数组A与B中均出现。

数据范围

对于40%的数据,保证1≤n,m≤1000。

对于100%的数据,保证1≤n,m≤105,1≤ai,bi≤109。

参考答案:

#include <iostream>

#include <set>

using namespace std;

int main() {

    int n, m;

    cin >> n>>m;

    set<int> setA;

    for (int i = 0; i < n; i++) {

        int x;

        cin >> x;

        setA.insert(x);

    }

    int count = 0;

    for (int i = 0; i < m; i++) {

        int x;

        cin >> x;

        if (setA.find(x) != setA.end()) {

            count++;

        }

    }

    cout << count << endl;

    return 0;

}

6.U432038 STL训练 壮志难酬

给你一个小数x,让你算出小数点后第n位是什么,(1 <= n <= 6)  

输入

包含多组测试数据。

首先输入一个t,表示有t组数据,跟着t行:

每行输入一个小数(输入数据保证一定是a.b的形式,为了简单化问题,没有循环小数的情况).然后跟一个n,表示小数点后第几位

输出

输出一个数表示小数点后第n位的数

样例输入

3

1.234 1

2.345 2

3.456 3

样例输出

2

4

6

参考答案:

#include <iostream>

#include <string>

using namespace std;

int main(){

    int n,index,c;

    string s;

    while(cin>>n){

        while(n--){

            cin>>s>>index;

            c=s.find(".");

            cout<<s[c+index]<<endl;

        }

    }

    return 0;

}

7.U432056:C语言1536: 蓝桥杯算法提高VIP-最长单词

题目描述

编写一个函数,输入一行字符,将此字符串中最长的单词输出。

输入仅一行,多个单词,每个单词间用一个空格隔开。单词仅由小写字母组成。所有单词的长度和不超过100000。如有多个最长单词,输出最先出现的。

样例输入

I am a student

样例输出

student

参考答案

#include<iostream>

#include<string>

using namespace std;

int main(){

         string s, m;

         int mmax = -1, num = 0;

         while (cin >> s){

               num = s.size();

               if (num > mmax){

                    mmax = num;

                           m = s;

                }

          }

          cout << m;

          return 0;

}

8.U432041 美国大选:C语言网 2060: 美国大选

题目描述

美国大选是按各州的投票结果来确定最终的结果的,如果得到超过一半的州的支持就可以当选,而每个州的投票结果又是由该州选民投票产生的,如果某个州超过一半的选民支持希拉里,则她将赢得该州的支持。现在给出每个州的选民人数,请问希拉里至少需要赢得多少选民的支持才能当选?

输入

多组输入数据

每组数据的第一行包括一个整数N(1<=N<=101),表示美国的州数,N=0表示输入结束。接下来一行包括N个正整数,分别表示每个州的选民数,每个州的选民数不超过100。

输出

对于每组数据输出一行,表示希拉里至少需要赢得支持的选民数

样例输入

3

5 7 5

0

样例输出

6

参考答案

#include<iostream>

#include<vector>

#include<algorithm>

using namespace std;

int main()

{

    int n;

    while(cin>>n&&n!=0){

        vector<int> vi;

        int num=0,temp;

        for(int i=0;i<n;i++){

         cin>>temp;

              vi.push_back(temp);

        }

        sort(vi.begin(),vi.end());

        for(int i=0;i<n/2+1;i++){

            num+=vi[i]/2+1;

        }

        cout<<num<<endl;

    }

    return 0;

}

7.U432039 :C语言网:[2162]信息学奥赛一本通-统计数字

题目描述

某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5∗10^9)。已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果。

输入

第一行是整数 n,表示自然数的个数;

第2~n+1每行一个自然数。

输出

包含m行(m为n个自然数中不相同数的个数),按照自然数从小到大的顺序输出。每行输出两个整数,分别是自然数和该数出现的次数,其间用一个空格隔开。

样例输入

8

2

4

2

4

5

100

2

100

样例输出

2 3

4 2

5 1

100 2

参考答案:

#include<iostream>

#include <string>

#include <map>

using namespace std;

int main(){

   map<long long,int> mymap;

    long long num;

    int n;

    cin>>n;

   while(n--){

   //find(key)在 map 容器中查找键为 key 的键值对,如果成功找到,则返回

   //指向该键值对的迭代器;反之,则返回和 end() 方法一样的迭代器。

       cin>>num;

        if(mymap.find(num)!=mymap.end()){

              ++mymap[num];

        }else{

              mymap[num]=1;

        }

    }

    map<long long,int>::iterator  iter;

    for(iter=mymap.begin();iter!=mymap.end();iter++){

        cout<<iter->first<<" "<<iter->second<<endl;

    }

    return 0;

}

9.U432058字符串比较

题目描述

给出了n(n<=100000)个由数字和字母组成的字符串(长度小于1000),求与给出字符串相同字符串的个数。

输入

第一行是一个数n。

接下来n行,每行都是一个字符串。

接下来一行,是待查询的字符串。

输出

输出一行,一个数。表示与待查询字符串相同的字符串个数。

样例输入

6

ase

eet

ase

see3

awqol

sss

ase

样例输出

2

参考答案:

#include<bits/stdc++.h>

using namespace std;

int main(){

    int n;

    string str;

    cin>>n;

    map<string,int> mp;

    for(int i=1;i<=n;i++){

        cin>>str;

//find(key)查找以key为键的键值对,如果找到,则返回一个指向该键值对的迭代器,

//反之,则返回一个指向容器中最后一个键值对之后位置的迭代器(end() 方法返回的迭代器)。

        if(mp.find(str)!=mp.end()){

          mp[str]+=1;

        }

        else{

          mp[str]=1;

       }         

    }

    cin>>str;

    cout<<mp[str];

    return 0;

}

10.U432060删除字符串中的重复元素

题目描述

本程序的功能是删除输入字符串中所有的重复元素。不连续的重复元素也要删除。

输入

一个字符串(不包含空格)

输出

删除重复元素之后的字符串。

样例输入

love2423445e1e96767878

样例输出

lov3519

参考答案:

#include <iostream>

#include <map>

using namespace std;

int main(){

    map<char, int> mp;

    string str;

    cin >> str;

    //当对map进行下标索引时,如果元素不存在,会自动创建,并赋默认0

    for (string::iterator it = str.begin(); it !=str.end(); it++)

        mp[*it] += 1;

    for (string::iterator it = str.begin(); it !=str.end();){

        if (mp[*it] > 1)

   //s.erase( const_interator pos )

   //删除 pos 迭代器所指的元素,返回值为下一个元素的迭代器

        it = str.erase(it);

        else

            it++;

    }

    cout << str << endl;

    return 0;

}

第8讲 并查集

1.P3367[模板]并查集

题目描述

如题,现在有一个并查集,你需要完成合并和查询操作。

输入格式

第一行包含两个整数 N,M表示共有 N个元素和 M个操作。

接下来 M 行,每行包含三个整数 Zi,Xi,Yi。

当 Zi=1 时,将 Xi与 Yi所在的集合合并。

当 Zi=2 时,输出 Xi与Yi是否在同一集合内,是的输出 Y ;否则输出 N 。

输出格式

对于每一个 Zi=2 的操作,都有一行输出,每行包含一个大写字母,为 Y 或者 N 。

输入

4 7

2 1 2

1 1 2

2 1 2

1 3 4

2 1 4

1 2 3

2 1 4

输出

N

Y

N

Y

参考答案

#include<bits/stdc++.h>

using namespace std;

int father[1000010];

int findFather(int x){

   int a = x;

   while(x !=father[x]){

        x=father[x];

   }

   while(a!=father[a]){

        int z=a; 

        a = father[a];

        father[z] =x;

   }

   return x;

}

void Union(int a,int b)

{

    int faA=findFather(a);

    int fbB=findFather(b);

    if(faA!=fbB)

    {

        father[faA]=fbB;

    }

}

int main(){

   int i,p1,p2,p3,n,m;

    cin>>n>>m;

    for(i=1;i<=n;i++)

        father[i]=i;

    for(i=1;i<=m;i++){

        cin>>p1>>p2>>p3;

        if(p1==1)

            Union(p2,p3);

        else

            if(findFather(p2)==findFather(p3))

                printf("Y\n");

            else

                printf("N\n");

    }

    return 0;

}

2. P8654 [蓝桥杯201国C]合根植物

w星球的一个种植园,被分成 m×n 个小格子(东西方向 m行,南北方向 n列)。每个格子里种了一株合根植物。

这种植物有个特点,它的根可能会沿着南北或东西方向伸展,从而与另一个格子的植物合成为一体。

如果我们告诉你哪些小格子间出现了连根现象,你能说出这个园中一共有多少株合根植物吗?

输入格式

第一行,两个整m,n用空格分开,表示格子的行数、列数(1<m,n<1000)。

接下来一行,一个整数 k,表示下面还有 k行数据 (0<k<10^5)。

接下来 k 行,第k行两个整数 a,b,表示编号为 a 的小格子和编号为 b 的小格子合根了。

格子的编号一行一行,从上到下,从左到右编号。

比如:5×4 的小格子,编号:

1  2  3  4 

5  6  7  8

9  10 11  12 

13  14  15  16 

17  18  19  20

输出格式

一行一个整数,表示答案

输入

5 4

16

2 3

1 5

5 9

4 8

7 8

9 10

10 11

11 12

10 14

12 16

14 18

17 18

15 19

19 20

9 13

13 17

输出

5

参考答案:

#include<bits/stdc++.h>

using namespace std;

int father[10000000];

//递归写法

/*int findFather(int v)

{

   if(v==father[v]) return v;

   else {

            int F=findFather(father[v]);

            father[v]=F;

            return F;

        }

}

*/

int findFather(int x){

   int a = x;

   while(x !=father[x]){

        x=father[x];

   }

   while(a!=father[a]){

        int z=a; 

        a = father[a];

        father[z] =x;

   }

   return x;

}

void Union(int a,int b){

    int faA=findFather(a);

    int fbB=findFather(b);

    if(faA!=fbB)

    {

        father[faA]=fbB;

    }

}

int main(){

   int i,a,b,n,m,k,sum=0;

    cin>>n>>m;

    for(i=1;i<=n*m;i++)

        father[i]=i;//初始化i的老大为自己

    cin>>k;

    for(i=0;i<k;i++){

        cin>>a>>b;  

        Union(a,b);

    }

    for(i=1;i<=n*m;i++){

         if(i==father[i])

             sum++;

    }

    cout<<sum;

    return 0;

}

3.U437610班级最高分

现有一个学校,学校中有若干个班级,每个班级中有若干个学生,每个学生只会存在于一个班级中。如果学生A和学生B处于一个班级,学生B和学生C处于一个班级,那么我们称学生A和学生C也处于一个班级。

现已知学校中共n个学生(编号为从1到n),每个学生有一个考试分数,再给出m组学生关系(指定两个学生处于一个班级),问总共有多少个班级,并按降序给出每个班级的最高考试分数。

输入描述

第一行两个整数n、m(1≤n≤100,1≤m≤100),分别表示学生个数、学生关系个数;

第二行为用空格隔开的n个整数(0≤每个整数≤100),表示n学生的考试分数;

接下来m行,每行两个整数a和b(1≤a≤n,1≤b≤n),表示编号为a的学生和编号为b的学生处于一个班级。

输出描述

第一行输出一个整数,表示班级个数;

第二行若干个整数,按降序给出每个班级的最高考试分数。整数之间用空格隔开,行末不允许有多余的空格。

样例1

输入

5 3

88 90 86 92 95

4 2

1 3

2 5

输出

2

95 88

解释

编号2、4、5的学生在同一个班级,编号1、3的学生在同一个班级,因此共有两个班级,最高分数分别是编号1的学生的88分、编号5的学生的95分。

参考答案:

#include<bits/stdc++.h>

using namespace std;

const int MAXN = 100;

int father[MAXN];

int score[MAXN];

vector<int> classes;

int findFather(int x){

   int a = x;

   while(x !=father[x]){

        x=father[x];

   }   

   while(a!=father[a]){

        int z=a; 

        a = father[a];

        father[z] =x;

   }

   return x;

}

void Union(int a, int b) {

    int faA = findFather(a);

    int faB = findFather(b);

    if (faA != faB) {

        if (score[faA] < score[faB]) {

            father[faA] = faB;

        } else {

            father[faB] = faA;

        }

    }

}

void init(int n) {

    for (int i = 1; i <=n; i++) {

        father[i] = i;

    }

}

int cmp(int a,int b){

   return a>b;   

}

int main() {

    int n, m, a, b;

    scanf("%d%d", &n, &m);

    init(n);

    for (int i = 1; i <=n; i++) {

        scanf("%d", &score[i]);

    }

    for (int i = 1; i <=m; i++) {

        scanf("%d%d", &a, &b);

        Union(a, b );

    }

    for (int i = 1; i <=n; i++) {

       if (father[i] == i) {           

classes.push_back(score[i]);

        }

    }

    sort(classes.begin(), classes.end(),cmp);

    printf("%d\n", classes.size());

    for (int i = 0; i < classes.size(); i++) {

        printf("%d", classes[i]);

        if (i < (int)classes.size() - 1) {

            printf(" ");

        }

    }

    return 0;

}


点赞(0)
 

0.0分

0 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 0 条评论

暂无评论