玩命加载中 . . .

洛谷官方题单——循环结构题解(水题警告)


今天虽然还是水题,但是实际上已经有部分需要一定的基础才能做出来。下面是代码和部分解释。

题目0:找最小值

这个地方方法很多,主要是因为n太小了导致了其随意做,但是我个人倾向于使用一边读入一边寻找最小值的方法,代码如下。

    int num,m=9999,temp;
    scanf("%d",&num);
    for(int i=0;i<num;i++){
        scanf("%d",&temp);
        m=min(m,temp);
    }
    return 0*printf("%d\n",m);

题目1:分类平均

我们只需要一边读入数据,一边判断他们是否能够满足被k整除,分别记录总和和个数即可,注意输出格式。

    int n,k,ks=0,kcnt=0,nks=0,nkcnt=0;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        if(i%k==0) ks+=i,kcnt++;
        else nks+=i,nkcnt++;
    }
    printf("%.1f %.1f",1.0*ks/kcnt,1.0*nks/nkcnt);
    return 0;

题目2:一尺之锤

按照题目的要求,一边除二一边计算日期就行了。(习惯用位运算,左移一位为除2,右移则为乘2)

    int n,cnt=0;
    scanf("%d",&n);
    while(n) n >>= 1,cnt++;
    return 0*printf("%d\n",cnt);

题目3:数字直角三角形

主要是对输出格式的处理,这里有有个小技巧,使用printf函数的时候采用%0xd的时候,可以在前面补0,x为位数。

    for(int i = 1;i <= n;i++){
        for(int j = 1;j <= n - i + 1;j++) 
            printf("%02d",cnt++);
        printf("\n");
    }

题目4:阶乘的和

高精度警告,因此这里的难度体现在用C/C++上,各位java选手和python选手请忽略

#include<iostream>
using namespace std;
int first[2000], ans[2000];
void Add(int* a, int* b) {
    int pos = 0;
    for (int i = 1; i <= 1000; i++) {
        b[i] += a[i] + pos;
        pos = b[i] / 10;
        b[i] %= 10;
    }
}
void Factorial(int* a, int b) {
    int pos = 0;
    for (int i = 1; i <= 1000; i++) {
        a[i] = a[i] * b + pos;
        pos = a[i] / 10;
        a[i] %= 10;
    }
}
int main() {
    int n, flag = 0;
    cin >> n;
    first[1] = 1;
    for (int i = 1; i <= n; i++) {
        Factorial(first, i);//求阶乘
        Add(first, ans);//从第一个数加到ans里面
    }
    for (int i = 1000; i >= 1; i--) {
        if (ans[i] != 0) flag = 1;
        if (flag) cout << ans[i];
    }
    return 0;
}

题目5:计数问题

算是比较基础的问题,求位数,当然也可以存到一个string数组里面,然后每个都是string,然后直接遍历变求string.strlen()之和。

#include<stdio.h>
int Count(x,num){
    int cnt = 0;
    while (x){
        if (num == (x % 10)) cnt++;
        x = x / 10;
    }
    return cnt;
}

int main(){
    int count = 0;
    long int n;
    int x;
    scanf("%ld%d", &n, &x);
    while (n){
        count += Count(n, x);
        n--;
    }
    return 0*printf("%d", count);
}

题目6:级数求和

如果你知道级数求和公式,那么没必要一步一步的来,但是如果你不知道直接循环即可。

#include<stdio.h>
int main(){
    long long int n,i = 1;
    scanf("%lld", &n);
    for (double sum = 0.0; sum <=n; i++)    sum += (1.0 / i);
    return 0*printf("%lld\n", i-1);//由于i从1开始取,由种树定理可知最后要-1
}

题目7:金币

简单的按照题目的要求即可。

# include <stdio.h>
int main()
{
    int k,cnt=0;
    scanf("%d",&k);               
    for(int n=1;k-n>=0;k-=n)      
        cnt+=n*n,n++;            
    return 0*printf("%d\n",cnt+k*n);//因为循环结束条件为k-n>=0,当k-n小于0的时候,
    //说明还留了一部分,所以需要加,当  k-n恰好等于0的时候,经过一轮循环以后,k直
    //接变为了0,这个部分就没了。
}

当然也可以按照数列求和地方法,高中老师告诉我们:1^2+2^2…+n^2=n(n+1)(2n+1)/6,1+2+3+…+n=n(n+1)/2。通过这两个就可以反解需要多少天才能达到之后超过,之前不够的天数,最后根据是否满足直接补上就行了,代码这里就不贴了,有兴趣的自己算一下。

题目8:数列求和

这上面这么多循环的数列求和了,这里最简单的数列求和就没有讲解必要了吧,题目不允许使用等差数列,那么,我们就选择使用他啦。

    return 0*printf("%d\n",n*-~n>>1);//这里牵扯到C语言比较细节的地方——计算优先级和位运算,看不懂还是老老实实写n*(n+1)/2吧

题目9:质数口袋

题目要求求出最多的质数个数以及求和要在给定的范围以内,所以我们只需要贪心从小到大直接选就vans了。

int isPrime(int y) {
    for(int i=2; i*i<=y; ++i) if(y%i==0) return 0;//这里牵扯到质数的性质,只需要判断小于其自身算数平方根的范围就行了,证明略
    return 1;
}
int main() {
    int n,x;
    long long sum=0;
    scanf("%d",&n);
    if(n<2) return 0*printf("0\n");
    else if(n==2) return 0*printf("2\n1\n");
    for(int i=2; i<=n; ++i) {
        if(i%2==0&&i!=2) continue;
        if(sum+i>n) return 0*printf("%d\n",x);
        if(isPrime(i)) {
            printf("%d\n",i);
            sum+=i;
            x++;
        }
    }
    return 0;
}

题目10:回文质数

按照题目要求,只需要从给定数字最近的一个质数开始就行了。

#pragma warning(disable:4996)//这个是在VS下不适用scanf_s的时候需要增加的宏定义,一般来说交题可以删掉,我忘了
#include<stdio.h>
#include<math.h>
#include<string.h>
bool book[10000050];//标记即可
void Is_Prime(int b) {
    memset(book+2, true, sizeof(bool) * 10000048);
    int n = sqrt(b);
    for (int i = 2; i <= n; i++) if (book[i]) for (int j = 2; j <= b / i; j++) book[i * j] = false;
}
bool Is_Palindromes(int num) {
    int temp = num, ans = 0;
    while (temp != 0) ans = ans * 10 + temp % 10, temp /= 10;
    return ans == num;
}
int main() {
    int a, b;
    scanf("%d%d", &a, &b);
    if (b >= 10000000) b = 9999999;//这里的原因是,牛逼“网友”证明得到,没有九位数的回文质数
    Is_Prime(b);
    if (a % 2 == 0) a++;
    for (int i = a; i <= b; i += 2) //这里的原因是因为,除了2,质数都不是偶数
        if (book[i] && Is_Palindromes(i)) printf("%d\n",i);
    return 0;
}

题目11:小玉在游泳

注意数据输入,计算过程和输出的要求格式。

#include<stdio.h>
#include<math.h>
int main(){
    double x,sum=0;
    int i;
    scanf("%lf",&x);
    for(i=0;sum<x;i++) sum+=2*pow(0.98,i);
    return 0*printf("%d",i);
}

题目12:数字反转(弱小版本)

有弱小必有加强,后面是有一个加强版本的,这里只需要注意前导0的存在就行了。

    int num;
    int ans = 0;
    scanf("%d", &num);
    while (num) ans = ans * 10 + num % 10,num /= 10;
    return 0 * printf("%d",ans);

题目13:月落乌啼算钱

如果你熟悉斐波那契数列,那么对于其解析式一定特别的熟悉,这道题的题干也给了很多的提示,同时fib数列也是理解和深入dp的一个重要入门手段。

    long long int f[50];
    int n;
    f[0]=0,f[1]=1,f[2]=1;
    scanf("%d",&n);
    for (int i=3;i<=n;i++) f[i]=f[i-1]+f[i-2];
    return 0*printf("%lld.00",f[n]); //题目毕竟要保证这个式子不能让人一下看出来就是整数嘛

题目14:求极差

一边输入一边保存最大最小值即可。

int main(){
    int min=99999,max=-999999,num,temp;
    scanf("%d",&num);
    for(int i=0;i<num;i++){
        scanf("%d",&temp);
        max=(max>temp?max:temp);
        min=(min<temp?min:temp);
    }
    return 0*printf("%d\n",max-min);
}

题目15:最长连号

我这里嫌一边输入一边记录麻烦,所以直接采用的是先全部存下来,然后直接进行遍历。

#include<stdio.h>
int memo[15000];
int main() {
    int num, ans = -1, temp_ans = 1;
    scanf("%d", &num);
    if (num == 1) return 0 * printf("1\n");
    for (int i = 0; i < num; i++) scanf("%d", &memo[i]);
    for (int i = 0; i < num; i++) {
        if (memo[i] + 1 == memo[i + 1]) temp_ans++;
        else temp_ans = 1;
        ans = (ans > temp_ans ? ans : temp_ans);
    }
    return 0 * printf("%d\n", ans);
}

题目16:质因数分解

由唯一分解定理可知:一个数能且仅能分解为一组若干质数的乘积,这里给出来的数据是一定是两个质数的乘积,只需要从小到大依次除,当能够除尽的时候,直接输出另一个数就行了

for (int i = 2; i <= num; i++) 
        if (num % i == 0) return 0 * printf("%d\n", num / i);

题目17:求三角形

输入输出题,前导0的补充方式在前面有,这里不赘述。

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) printf("%02d", start++);
        printf("\n");
    }
    printf("\n");
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (j + i + 1 < n) printf("  ");
            else printf("%02d", sstart++);
        }
        printf("\n");
    }

题目18:打分

求最低最高,在数据比较多的情况可以使用极差那道题的方式,但是这里我采用的是使用sort函数,虽然会慢一些,但是代码更加精简。

#include<stdio.h>
#include<algorithm>
int memo[1005];
int main() {
    int n,sum=0;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) scanf("%d", &memo[i]);
    std::sort(memo, memo + n);//你也可以在前面使用名称空间
    for (int i = 1; i < n - 1; i++) sum += memo[i];
    return 0 * printf("%.2lf\n", sum * 1.0 / (n - 2));
}

题目19:Davor

因为每个周一到周日所筹集的钱是一样的,所以把钱的总额直接就加起来就行了。

    for (k = 1;; ++k)
        for (x = 100; x > 0; --x)
            if ((7 * x + 21 * k) * 52 == n) 
                return 0*printf("%d\n%d\n", x, k);

题目20:津津的储蓄计划

实际上按照题目要求从1月到12月遍历一次即可。

#include<stdio.h>
int main(){
    int a[12],re = 0,c,st = 0;//re即remain剩余,st即store存储,c为consume消耗后还有的整百部分
    for (int i = 0; i < 12; i++)  scanf("%d", &a[i]);
    for (int i = 0; i<12; i++){
        c = (re + 300 - a[i] )/ 100;
        re = re + 300 - a[i] - c * 100;
        st =st+ c * 100;
        if (re<0){//这里说明剩下的钱不够了
                i++;
                printf("-%d\n", i);
                break;
            }
    }
    if (re>0) printf("%d\n", st*120/100 + re);
    return 0;
}

以上就是本篇的全部内容啦,如果有问题的话可直接联系我的QQ(在下方可以加)。


文章作者: AleXandrite
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 AleXandrite !
  目录