Bootstrap

C语言课程设计——25道蓝桥杯练习题

文章目录

一、基础练习

1.fib数列

题目

题目链接

Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1。当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少。

数据规模与约定

1 <= n <= 1,000,000。

解题思路

很明显,数据规模并不大,O(n)时间复杂度便可解决。

但如果数据规模非常庞大,我们可以利用到下面这张图的矩阵递推公式再根据矩阵快速幂解决:

image-20211227203236820

解题代码

解法一(简单递推):时间复杂度O(n)

适用于数据量少于10^8的情况

#include <stdio.h>
const int MOD = 10007;
int main() {
   
    int n;
    scanf("%d", &n);
    int a=1,b=1;
    if(n<=2)printf("1");
    else{
   
        int tmp;
				int i;
        for(i=3;i<=n;i++) {
   
            tmp = b;
            b = (a+b)%MOD;
            a = tmp;
        }
        printf("%d",b);
    }
    return 0;
}
解法二(矩阵快速幂):时间复杂度O(logn)

适用于数据量大于10^8的情况

//
// Created by Alone on 2021/11/19.
//
#include <bits/stdc++.h>
using namespace std;

typedef long long ll ;

//TODO To design a matrix class to solve this problem
class Matrix{
   
    ll** date;
    int m;
    int n;
public: static const int MOD;
public:
    Matrix(ll** rec,int n,int m):date(rec),n(n),m(m){
   }//C format to init
    Matrix():date(NULL),m(0),n(0){
   } //aefault
    Matrix(Matrix& b):n(b.n),m(b.m){
   //copy struct
        assert(b.date!=NULL && b.n>0 && b.m>0);
        date = new ll*[n];
        copy(b.date,b.date+n,date);
        for(int i=0;i<n;i++){
   
            date[i] = new ll[m];
            copy(b.date[i],b.date[i]+m,date[i]);
        }
    }
    ~Matrix(){
   //destruct
        assert(date!=NULL && n>0 && m>0);
        for (int i = n-1; i >=0 ; --i) {
   
            delete [] date[i];
        }
        delete[] date;
    }
    Matrix& operator*(Matrix& b){
   //TODO operator* to overload
        assert(b.date!=NULL && date!=NULL && m==b.n);
        ll tmp[n][b.m];
        for(int i=0;i<n;i++){
   
            for(int j=0;j<b.m;j++){
   
                ll sum = 0;
                for(int k=0;k<m;k++){
   
                    sum = (sum + date[i][k]*b.date[k][j])%MOD;
                }
                tmp[i][j] = sum;
            }
        }
        this->m = b.m;
        for(int i=0;i<n;i++){
   
            for (int j = 0; j < m; ++j) {
   
                date[i][j] = tmp[i][j];
            }
        }
        return *this;
    }
    void init(){
   //TODO initialized to unit matrix
        assert(date!=NULL && n>0 && m>0);
        for (int i = 0; i < n; ++i) {
   
            for (int j = 0; j < m; ++j) {
   
                if(i==j)date[i][j] = 1;
                else date[i][j] = 0;
            }
        }
    }
    void quickPow(ll c){
   //TODO quick pow for matrix
        if(c==1||c<0)return;
        if(c==0){
   
            init();
            return;
        }
        Matrix tmp(*this);
        init();
        while (c){
   
            if(c&1)
                *this = *this * tmp;
            c >>= 1;
            tmp = tmp*tmp;
        }
    }
    void print(){
   //TODO to print this matrix
        for(int i=0;i<n;i++){
   
            for(int j=0;j<m;j++){
   
                cout<<date[i][j]<<' ';
            }
            cout<<endl;
        }
    }
    int get(int x,int y){
   //TODO provide access to the outside
        assert(date!=NULL && x<n && y<m);
        return date[x][y];
    }
};
const int Matrix::MOD = 1007;//TODO set the factor for mod operation

int main(){
   
    ll c;
    cin>>c;
    ll** matrix = new ll*[2];
    matrix[0] = new ll[2]{
   1,1};
    matrix[1] = new ll[2]{
   1,0};
    Matrix mat(matrix,2,2);
    mat.quickPow(c-1);

    ll** res = new ll*[2];
    res[0] = new ll[1]{
   1};
    res[1] = new ll[1]{
   1};
    Matrix fib(res,2,1);
    Matrix ret(mat*fib);
    cout<<ret.get(1,0);
    return 0;
}


2.闰年判断

题目

题目链接

解题思路

只要挑选处闰年即可,闰年有个判断方式将其判断:

关于闰年的解释:

  1. 普通年份能被4整除,且不能被100整除的,是闰年。( 如2004年就是闰年)
  2. 世纪年份能被400整除的是闰年。( 如2000年是闰年,1900年不是闰年)

如果年份是闰年,那么它的二月份就会比平常多1天。

解题代码

#include<stdio.h>
int main(){
   
    int n;
    const char* res[]= {
   "no","yes"};
    scanf("%d",&n);
    int index = 0;
    if(n%400==0||(n%4==0&&n%100!=0))
        index = 1;
    fputs(res[index],stdout);
    return 0;
}

3. 数列特征

题目

题目链接

解题思路

求一个数组的最大值和最小值以及所有数字的和。。

解题代码

#include<iostream>
#include<algorithm>
#include<limits>
using namespace std;
int main(){
   
    int n;
    cin>>n;
    int nums[n];
    int mx=INT_MIN,mn=INT_MAX,sum = 0;
    for(int i=0;i<n;i++){
   
        cin>>nums[i];
        mx = max(mx,nums[i]);
        mn = min(mn,nums[i]);
        sum += nums[i];
    }
    printf("%d\n%d\n%d",mx,mn,sum);
    return 0;
}

4.查找整数

题目

题目链接

解题思路

按照题目意思来就行,直接查找第一次出现的位置即可。

解题代码

解法一:C风格
#include <iostream>
using namespace std;

int main(){
   
    int n,target;
    int res = -1;
    cin>>n;
    int nums[n];
    for(int i=0;i<n;i++){
   
        cin>>nums[i];
    }
    cin>>target;
    for (int i = 0; i < n; ++i) {
   
        if(nums[i]==target){
   
            res = i+1;
            break;
        }
    }
    cout<<res;
    return 0;
}
解法二:C++风格

由于C++98不支持lamda表达式,所以需要把传入的函数单独写出来了。

#include <bits/stdc++.h>
using namespace std;
void input(int& a){
   cin>>a;}
int main(){
   
    int n,target,res;
    cin>>n;
    int nums[n];
    for_each(nums,nums+n,input);
    cin>>target;
    res = find(nums,nums+n,target)-nums+1;
    if(res>n)
        res = -1;
    cout<<res;
    return 0;
}

C++11风格

#include <bits/stdc++.h>
using namespace std;
int main(){
   
    int n,target;
    int res;
    cin>>n;
    int nums[n];
    for_each(nums,nums+n,[](int& a){
   cin>>a;});
    cin>>target;
    res = find(nums,nums+
;