Bootstrap

“蓝桥杯”练习系统(基础篇)

“蓝桥杯”练习系统(基础篇)


一、基础训练

  1. 数列排序

image-20230228181234509

解法:排序算法-冒泡排序

关键字:数组 排序

函数封装:

#include<bits/stdc++.h>
using namespace std;

void BubbleSort(int a[],int n){
	int temp=0;
	for(int i=0;i<n-1;i++){
		for(int j=0;j<n-1-i;j++){
			if(a[j]>a[j+1]){
				temp=a[j];
				a[j]=a[j+1];
				a[j+1]=temp; 
			}
		}
	}
}

int main(){
	int n;
	cin>>n;
	int a[n];
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	BubbleSort(a,n);
	for(int i=0;i<n;i++){
		cout<<a[i]<<" ";
	} 
	return 0;
}

#include<bits/stdc++.h>
using namespace std;

int main(){
	int n;
	cin>>n;
	int a[n];
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	int temp=0;
	for(int i=0;i<n-1;i++){
		for(int j=0;j<n-1-i;j++){
			if(a[j]>a[j+1]){
				temp=a[j];
				a[j]=a[j+1];
				a[j+1]=temp; 
			}
		}
	}
	for(int i=0;i<n;i++){
		cout<<a[i]<<" ";
	} 
	return 0;
}

C++ sort():

#include<bits/stdc++.h>
using namespace std;

int main(){
	int n,a[n];
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	sort(a,a+n);
	for(int i=0;i<n;i++){
		cout<<a[i]<<" ";
	}
} 

image-20220302101942317

时间复杂度:O(n2)

思考过程:

  1. 一开始想着封装成函数进行计算,想着函数的返回成一个数组回来,查询后

    https://www.baidu.com/s?ie=UTF-8&wd=C++%E8%BF%94%E5%9B%9E%E7%B1%BB%E5%9E%8B%E4%B8%BA%E6%95%B0%E7%BB%84

    答案:

    https://zhidao.baidu.com/question/337749783.html

    是没有返回类型为数组类型,详情查看:https://zhidao.baidu.com/question/380269428.html

    思路1:但可以这样,参数为int类型数组,返回为vector数组。直接将排序好的数组返回

    思路2:C语言存在引用,由于数组是指针,作为参数传递不是复制,而是直接改变本身,所以把函数的返回值设为void,调用函数,数组本身排序,直接在main输出即可

  2. 排序算法遗忘,看的是Java代码写的冒泡排序(由于n<200,数据量小,可以使用冒泡排序)。

    C++与Java的一些对比:

    • https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&tn=baidu&wd=c%E8%AF%AD%E8%A8%80%E8%83%BD%E5%83%8Fjava%E4%B8%80%E6%A0%B7length&oq=c%25E8%25AF%25AD%25E8%25A8%2580%25E6%2580%258E%25E4%25B9%2588%25E5%25BE%2597%25E5%2588%25B0%25E6%2595%25B0%25E7%25BB%2584%25E7%259A%2584%25E9%2595%25BF%25E5%25BA%25A6&rsv_pq=ad4897210006b483&rsv_t=eff3ANdrFh1Th3Aq3I%2B6mHT0edGD8utji4h72oo4vMy3eLHx3YbGjkh0HGI&rqlang=cn&rsv_enter=1&rsv_dl=tb&rsv_sug3=45&rsv_sug1=24&rsv_sug7=100&rsv_sug2=0&rsv_btype=t&inputT=14377&rsv_sug4=15003

      在Java中可以直接获得数组的大小(arr.length)

      而C++不能这样知道,要么定好固定值数组大小n(所以要cin>>n)

      或https://www.jb51.net/article/205038.htm

      https://blog.csdn.net/weixin_37536484/article/details/78686028

      (一开始想strlen函数求解长度,后来查看后发现是只能求字符串的长度【由于C语言中没有字符串类型,以字符数组作为字符串】https://baike.baidu.com/item/strlen/2737?fr=aladdin;http://c.biancheng.net/c/strlen.html。C++中采用String类型:https://www.cnblogs.com/limera/p/5468551.html)

    #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
    char a[] = { 1,2,3,4 };
    length_a = ARRAY_SIZE(a);
    printf("length of a[]=%d\n", length_a);
    
    • Java的数组可以通过Array直接输出

      System.out.println(Arrays.toString(arr));
      

      而C++数组只能通过循环遍历输出

      为此还专门查了https://blog.csdn.net/weixin_34257076/article/details/92583249

  3. 在写完程序后,想着用函数封装试下,结果太久没有写数组作为函数参数,忘记怎么写;且主函数传递也写错

    #include<bits/stdc++.h>
    using namespace std;
    
    void BubbleSort(int a[n]){ //错误点1:因为函数体中有n,写了n
        					   //正确写法:int *a(int a[])
    	int temp=0;
    	for(int i=0;i<n-1;i++){
    		for(int j=0;j<n-1-i;j++){
    			if(a[j]>a[j+1]){
    				temp=a[j];
    				a[j]=a[j+1];
    				a[j+1]=temp; 
    			}
    		}
    	}
    }
    
    int main(){
    	int n;
    	cin>>n;
    	int a[n];
    	for(int i=0;i<n;i++){
    		cin>>a[i];
    	}
    	BubbleSort(a[n]);  //错误点2:数组传递方式错误  数组直接是引用,不用&
    	for(int i=0;i<n;i++){
    		cout<<a[i]<<" ";
    	} 
    	return 0;
    }
    
    

    正确写法:

    https://www.baidu.com/s?ie=UTF-8&wd=C%E8%AF%AD%E8%A8%80%E6%95%B0%E7%BB%84%E4%BD%9C%E4%B8%BA%E5%8F%82%E6%95%B0

    https://blog.csdn.net/weixin_41789607/article/details/80155839


  1. 十六进制转十进制

image-20230228181300534

解法:枚举 数学规律

关键字:进制转换 字符处理 判断

#include<iostream>
#include<string>
#include<math.h>//下面的pow,需要
using namespace std;
int main()
{
	string a;
	cin >> a;
    char b[16] = {		'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
	int c[10];
	int k = a.length() - 1;//目的对应好幂的次方
	for (int j = 0; j < a.length(); j++)
	{
		for (int i = 0; i < 16; i++)  //b数组大小16 
		{
			if (a[j] == b[i])
			{
				c[k--] = i;//因为string类型接收的时候,高次在数组低位(例如:string a=“FAB”,								a[0]=F,a[1]=A,a[2]=B),所以将高次存在数组高位,以此变正向
			}
		}
	}
	long long int sum = 0;//应对sum的值超了int的范围
	for (int i = 0; i < a.length(); i++)
	{
		sum += c[i] * pow(16, i);//这简化转的过程;pow 16的i次方
	}
	cout << sum << endl;
	return 0;
}

image-20220302101910413

时间复杂度:O(n2)

思考过程:

  1. 首先复习下有关进制方面的知识:https://www.baidu.com/s?ie=UTF-8&wd=C++%E8%BF%9B%E5%88%B6

    https://www.jb51.net/article/83754.htm

    http://c.biancheng.net/view/1759.html

    十六进制、八进制不是很熟,比较熟悉的为十进制、二进制

    先对输入格式进行分析:要求输入十六进制数(不明白A~F在十六进制代表什么?)

    十六进制数的基数是16,采用的数码是0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F。其中A-F分别表示十进制数字10-15。

    通常,对十六进制数的表示,可以在数字的右下角标注16或H,**但在C语言中是在数的前面加数字0和字母X即0X来表示,以数字“0”加上“x”或“X”开关都是十六进制数。**例如,十进制数12AF在C语言中表示为0X12AF。

    image-20230228181328273

    例如:0X1A(或0x1A)的十六进制数相当于十进制数的26=16+10(1→16,A→10)

  2. 解题思路:

    http://c.biancheng.net/view/1725.html

    《算法笔记》P93,思想正确,代码只能计算纯数值的,有些问题

    图解:

  3. 所使用到的库函数:

    pow:https://www.runoob.com/cprogramming/c-function-pow.html

    strlen:https://blog.csdn.net/weixin_42427338/article/details/90109813(char array,string都可)

    sizeof:https://baike.baidu.com/item/sizeof/6349467?fr=aladdin

  4. 在C++中引入头文件#include(引入string类)可以定义string类型的字符串,而C语言中只有字符数组来代替字符串(没有类的概念)。string类型像Java一样,有str.length()方法,且能够通过下标查询到每个元素(像C语言字符数组一样)。https://blog.csdn.net/weixin_39624071/article/details/117016894

    在C语言中,char类型数组有两种常见的赋值方式(https://blog.csdn.net/yjh0628/article/details/5830133)

    • 方式一:直接使用字符串赋值

      这种方式是将string转换成charater array,末尾有’/0’(string类型结束标识),故sizeof(array)的大小为数组元素+1。建议在定义数组时,不指定数组的大小,直接赋值。

    • 方式二:对数组中逐一元素赋值

      这种方式在定义数组时,既可以指定数组大小,也可以不指定。

  5. 最后,在来说下两次方案提交结果为75分的分析:

    image-20220302103319929

    • 方案一:https://blog.csdn.net/weixin_52340203/article/details/114649867?spm=1001.2101.3001.6650.7&utm_medium=distribute.pc_relevant.none-task-blog-2defaultBlogCommendFromBaiduRate-7.pc_relevant_antiscan&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2defaultBlogCommendFromBaiduRate-7.pc_relevant_antiscan&utm_relevant_index=11
    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
    //	char S[] = "0123456789ABCDEF";
    	char S[] ={ '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; 
    	char sixteen[8];
    	cin>>sixteen;
    	int ten=0;
    	int j = 1;
    	long long int len = strlen(sixteen);
    	for (int i = 0;i < len;i++) {
    		int a;
    		if (sixteen[len - 1 - i] >= '0' && sixteen[len - 1 - i] <= '9') {
    			 a = sixteen[len - 1 - i] - '0';
    		}
    		else {
    			for (int j = 0;j < 16;j++) {
    				if (sixteen[len - 1 - i] == S[j]) {
    					 a = j;
    				}
    			}
    		}
    		ten = ten + a * j;
    		j = j * 16;
    	}
    	cout<<ten; 
    }
    

    查看了这篇https://codeleading.com/article/89375374672/后,自己测试后,确实FFFFFFFF最大的情况返回值为-1,计算不了

    猜测:https://codeleading.com/article/89375374672/

    • 方案二:后面看到一篇Java版的https://blog.csdn.net/wnamej/article/details/105587896

    一开始看到string转char array很迷惑,认为string都可以用下标取元素,为什么还要转char

    查找到C++的string转char array的方法:https://www.cnblogs.com/Pillar/p/4206452.html

    #include<bits/stdc++.h>
    using namespace std;
    
    int main(){
    	string str;
    	cin>>str;
    	int len=str.length();
    	
    //	for(int i=0;i<len;i++){
    //		cout<<str[i];
    //	}
    
    //	cout<<endl<<len;
    	long a[len];
    	long sum=0L;
    	
    	for(int i = len-1; i >= 0; i--){
    		//定义十六进制的权位
    		long sixteen = 1;
    		for(int j = 1; j < len-i; j++){
    			sixteen *= 16;
    		}
    		//判断十六进制中的字符是否是字母
    		if(str[i] >= 'A' && str[i] <= 'Z'){
    			a[i] = str[i]-55;
    			sum += a[i]*sixteen;
    		}else{
    			a[i] = str[i]-48;
    			sum += a[i]*sixteen;
    		}
    	}
    	cout<<sum<<endl;
    	return 0;
    }
    
    

    总结:按照博客的分析,猜想两个方面,一、数据太大,long long放不下。二、可能是涉及ASCII表相关方面换算有问题

    对于第一点,可以查看欧拉计划笔记16题,利用数组存数值,改进。


  1. 十进制转十六进制

    image-20230228181357202

    解法:枚举 数学规律

    关键字:循环 整除 求余 判断

    #include<bits/stdc++.h>
    using namespace std;
    
    int main(){
    	int ten;
        cin>>ten;
        if(ten==0) {
            cout<<'0'<<endl; 
    		return 0;
        }
        string s="0123456789ABCDEF";
        string sixteen="";
        int i;
        while(ten>0){
            i=ten%16;
            sixteen+=s[i];
            ten=ten/16;
        }
        //倒序输出 
        for(int j=sixteen.length();j>0;j--){
    		cout<<sixteen[j-1];  //因为length()比真实下标 
    	} 
        cout<<endl;
        return 0;
    } 
    

    image-20220302105623303

    时间复杂度:O(n2)

    思考过程:

    ​ 图解:


  1. 十六进制转八进制

image-20230228181415449

解法:枚举 数学规律

关键字:进制转换 字符 循环

时间复杂度:O(n2)

思考过程:

  1. 注意下题目的要点
    • 每个十六进制数长度不超过100000
    • 输入与输出的十六进制数与八进制数不会有前导0

  1. 特殊回文数

image-20230228181429604

解法:枚举

关键字:回文数 循环 条件语句

#include<bits/stdc++.h>
using namespace std;

int main(){
	int n;
	cin>>n;
	//五位数的回文数 
	for(int i=1;i<=9;i++){
		for(int j=0;j<=9;j++){
			if((i+j)*2<=n&&(i+j)*2>=n-9){  //保证第三个数在0-9之间
				cout<<i<<j<<(n-i-i-j-j)<<j<<i<<endl; 
			}
		}
	} 
	
	//六位数的回文数
	for(int k=1;k<=9;k++){
		for(int m=0;m<=9;m++){
			for(int g=0;g<=9;g++){
				if(k+k+m+m+g+g==n){
					cout<<k<<m<<g<<g<<m<<k<<endl;;
				}
			}
		}
	} 
} 

image-20220305214420251

时间复杂度:O(n3)

思考过程:

  1. 注意下题目的要点

    • 求所有的五位与六位十进制数
    • 隐含条件:数字的首尾不能为0
  2. 启发:

    对于回文数,时刻铭记尽可能使用较小的循环实现枚举

    无论对于5位的回文数还是6位的回文数,利用这样的思想:因为每个数会出现两次,利用尽可能少的变量实现对剩余数的表示,以实现较小循环的实现。

  3. 收获:

    循环次数较少的,能够写到三重循环以上


  1. 回文数

image-20230228181446366

解法:枚举

关键字:循环 判断 回文数

#include<bits/stdc++.h>
using namespace std;

int main(){
	for(int i=1;i<=9;i++){
		for(int j=0;j<=9;j++){
			cout<<(i*pow(10,3)+j*pow(10,2)+j*pow(10,1)+i*pow(10,0))<<endl;
		}
	}
}

image-20220305215334490

时间复杂度:O(n2)

思考过程:

​ 这道题同样是利用回文数每次出现两个,结合十进制数值转化实现


  1. 特殊的数字

  1. 杨辉三角形

image-20230228181506143

image-20230228181514693

解法:枚举

关键字:基础练习 二维数组

#include<bits/stdc++.h>
using namespace std;

int main(){
	int n;
	cin>>n;
	int a[n][n];
	for(int i=0;i<n;i++){
		a[i][0] = a[i][i] =1;
	}
	for(int i=2;i<n;i++){
		for(int j=1;j<i;j++){
			a[i][j] = a[i-1][j]+a[i-1][j-1];
		}	
	}	
	for(int i=0;i<n;i++){
		for(int j=0;j<=i;j++){
			cout<<a[i][j]<<" ";
		}
		cout<<endl;
	}
	return 0;
} 

时间复杂度:O(n2)

思考过程:

​ 首先找到杨辉三角的特征及规律

​ https://www.cnblogs.com/clover-toeic/p/3766001.html

​ https://blog.csdn.net/qq_32489573/article/details/101164998

​ https://www.baidu.com/s?ie=UTF-8&wd=0%EF%BC%81%E7%AD%89%E4%BA%8E


  1. 查找整数

image-20230228181529562

解法:查找算法—顺序查找

关键字:循环 判断

#include<bits/stdc++.h>
using namespace std;

int main(){
	int n;
	cin>>n;
	int a[n];
	//一行连续输入就不能用循环 
	for(int i=0;i<n;i++){  //一行输入(因为有空格)或竖列输入都行 
		cin>>a[i];
		//cout<<a[i];
	}
	int search;
	cin>>search;
	bool find =true;
	//cout<<search;
	for(int i=0;i<n;i++){
		if(a[i]==search){
			//cout<<"a[i]:"<<a[i]<<endl;
			find=false;
			cout<<i+1<<endl;
			break;
		}
	}
	if(find){
		cout<<-1<<endl;
	}
	return 0;
}

image-20220306215917286

时间复杂度:O(n2)

思考过程:

  1. 首先要具备七大查找算法的知识:https://blog.csdn.net/yimixgg/article/details/88900038

    该题由于数据不复杂,直接使用顺序查找即可

  2. 由于之前没有注意题目条件,未查找到的返回-1,使得测试结果为20

    image-20220306220155478

    #include<bits/stdc++.h>
    using namespace std;
    
    int main(){
    	int n;
    	cin>>n;
    	int a[n];
    	for(int i=0;i<n;i++){  //一行输入或竖列输入都行 
    		cin>>a[i];
    		//cout<<a[i];
    	}
    	int search;
    	cin>>search;
    	//cout<<search;
    	for(int i=0;i<n;i++){
    		if(a[i]==search){
    			//cout<<"a[i]:"<<a[i]<<endl;
    			cout<<i+1;
    			break;
    		}else{
    			cout<<-1;
    			break;
    		}	
    	}
    	return 0;
    }
    

    题解:

    巧妙之处:利用bool判断

    https://www.cnblogs.com/loveluking/p/6067661.html


  1. 数列特征

  1. 字母图形

  1. 01字串

  1. 闰年判断

image-20220305220026132

image-20230228181609195

解法:枚举

关键字: 条件判断

#include<bits/stdc++.h>
using namespace std;

int main(){
	int y;
	cin>>y;
	while(y!=0){
		if(y%4==0&&y%100!=0||y%400==0){  //倍数判断取余,而不是除(除要多重循环) 
			cout<<"yes";
			break;
		}else{
			cout<<"no";
			break;
		}
	}
	return 0; 
}

v

时间复杂度:O(n)

思考过程:

​ 判断一个数是不是另一个数的倍数,看这个数循环除另一个数最终结果是不是==0,而取余%就是以上过程的实现。


  1. Fibonacci数列

image-20230228181719100

image-20230228181730207

解法:递推

关键字: 入门 数列 取模

#include<bits/stdc++.h>
using namespace std;

int main(){
	int n,f1=1,f2=1,f;
	cin>>n;
	if(n<=2){
		cout<<1;
	}else{
		for(int i=3;i<=n;i++){
			f=(f1+f2)%10007;
			f1=f2;
			f2=f;
		}
		cout<<f;
	}
	return 0;
}

image-20220306214038085

时间复杂度:O(n)

思考过程:

  1. 注意下题目的要点

    • 不用求出Fn的准确值,只需要求余数
  2. 常见情况下,我们求解斐波那契数列都是采用“递归“的方式,当由于题目所要求的n太大,递归的方式计算会出现超时,且从F1推导到Fn思路清晰,故采用”递推的方式进行计算。

    image-20220306213727279

    #include<bits/stdc++.h>
    using namespace std;
    
    int f(int n){
    	int result; 
    	if(n==1||n==2){
    		result=1;	
    	}else#include<bits/stdc++.h>
    using namespace std;
    
    int main(){
    	int n;
    	cin>>n;
    	int a[n][n];
    	for(int i=0;i<n;i++){
    		a[i][0] = a[i][i] =1;
    	}
    	for(int i=2;i<n;i++){
    		for(int j=1;j<i;j++){
    			a[i][j] = a[i-1][j]+a[i-1][j-1];
    		}	
    	}	
    	for(int i=0;i<n;i++){
    		for(int j=0;j<=i;j++){
    			cout<<a[i][j]<<" ";
    		}
    		cout<<endl;
    	}
    	return 0;
    } 
    		result=f(n-1)+f(n-2);
    	}
    	return result;
    }
    
    int main(){
    	int n;
    	cin>>n;
    	cout<<f(n)%10007;
    	return 0;
    } 
    
  3. 递推与递归的区别:

    https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&tn=baidu&wd=%E9%80%92%E6%8E%A8&oq=%25E9%2580%2592%25E6%258E%25A8%25E5%2592%258C%25E9%2580%2592%25E5%25BD%2592%25E7%259A%2584%25E5%258C%25BA%25E5%2588%25AB&rsv_pq=ef581ad0001cfab9&rsv_t=7fdf6wPuO4Fuj59oE7m%2FsGLqeN5Xl415xY%2FAGtRMXvzMTascGsSJTKUfZ6g&rqlang=cn&rsv_enter=1&rsv_dl=tb&rsv_btype=t&inputT=277&rsv_sug3=7&rsv_sug1=7&rsv_sug7=100&rsv_sug2=0&rsv_sug4=874

    https://blog.csdn.net/weixin_44143702/article/details/86551826

    https://blog.csdn.net/lybc2019/article/details/104080425

  4. 接着分析为什么是在每次循环%10007(f=(f1+f2)%10007;),而不是在最后算出Fn在%10007(Fn%10007)。题目已经给我们了提示,因为所定义的int变量可能会超出范围。

    image-20220306215637911

    #include<bits/stdc++.h>
    using namespace std;
    
    int main(){
    	int n,f1=1,f2=1,f;
    	cin>>n;
    	if(n<=2){
    		cout<<1%10007;
    	}else{
    		for(int i=3;i<=n;i++){
    			f=f1+f2;
    			f1=f2;
    			f2=f;
    		}
    	}
    	cout<<f%10007;
    	return 0;
    }
    

    很多人可能会想问,为什么每次循环取余数就能够保证最后的结果是正确的?(这样的提问是数据量大,比较抽象的原因造成的)

    举例:(自己也没想明白)

    假设一开始是1,1%10007的余数还是1本身,所以但数字<10007的时候,每次循环变量f不会因为取余而改变的,故按照提示是能够保证最后的结果正确。

    题解:

    https://www.cnblogs.com/loveluking/p/6031534.html

    https://www.freesion.com/article/20611273335/


  1. 圆的面积

image-20230228181809949image-20230228181822515

解法:数学方法

关键字:入门 实数输出

#include<bits/stdc++.h>
using namespace std;

int main(){
	int r;
	cin>>r;
	double area;
	area=r*r*M_PI;
	printf("%.7f",area);
	return 0;
}

image-20220306195841529

#include<bits/stdc++.h>
using namespace std;
#define PI 3.14159265358979323 
int main(){
	int r;
	cin>>r;
	double area;
	area=r*r*PI;
	printf("%.7f",area);
	return 0;
}

image-20220306195910020

时间复杂度:O(1)

思考过程:

  1. 注意下题目的要点:

    • 输入的是一个整数,输出的是一个实数 → 涉及类型的转换
    • 要求保留七位小数,四舍五入 → C语言在类型转换时是不会四舍五入的
  2. 收获:

    • 在查找相关资料的时候发现,以前我们往往需要自己定义圆周率,C语言的math.h的头文件中提供M_PI宏来表示圆周率

      https://blog.csdn.net/qq_40634846/article/details/86618802

      https://zhidao.baidu.com/question/564337042.html

    • 涉及C语言四舍五入的问题时,C++程序也需要使用C语言的输出方式printf()来控制输出格式

      https://blog.csdn.net/whalefall/article/details/80297752

      关于保留n位小数的输出形式

      https://blog.csdn.net/qq_41113008/article/details/89293673

      以及保留n位小数四舍五入问题:

      https://www.baidu.com/s?ie=UTF-8&wd=c%E8%AF%AD%E8%A8%80%E6%98%AF%E8%87%AA%E5%8A%A8%E5%9B%9B%E8%88%8D%E4%BA%94%E5%85%A5%E5%90%97

      https://zhidao.baidu.com/question/460172887705565805.html

  3. 关于第一次得到10分的分析:

    image-20220306195949549

    image-20220306200032205

    所定义的圆周率长度不够,计算出现问题

    因为圆周率不好记忆,建议还是使用头文件math.h下提供的M_PI宏


  1. 序列求和

image-20230228181907390

image-20230228181917579

解法:数学方法—高斯等差数列求和公式/枚举

关键字:入门 求和公式

枚举:

#include<bits/stdc++.h>
using namespace std;

int main(){
	long long n,sum=0;
	cin>>n;
	for(long long i=1;i<=n;i++){
		sum+=i;
	}
	cout<<sum;
	return 0; 
} 

image-20220307202349040

时间复杂度:O(n)

高斯等差数列求和公式:(首项+末项)*项数/2=数列和

#include<bits/stdc++.h>
using namespace std;

int main(){
	long long n,sum=0;
	cin>>n;
	sum=(1+n)*n/2;
	cout<<sum;
	return 0; 
} 

image-20220307202458778

时间复杂度:O(1)

看可以看到两者的时间差距还是很明显的

思考过程:

  1. 注意下题目的要点:

    数据规模与约定

    1 <= n <= 1,000,000,000(10位)<long long (19位)。

    上次遇到这么大规模的数据还是“欧拉计算刷题笔记中16题求2的幂的时候”,在这统一笔记并复习下C/C++的数据基本类型:

    https://www.runoob.com/cprogramming/c-data-types.html

    https://blog.csdn.net/qq_38410730/article/details/80138714?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-1.pc_relevant_paycolumn_v3&spm=1001.2101.3001.4242.2&utm_relevant_index=4

    (说明:unsigned int=int,short int =short,long int =long,long long = long long int)

    注意:int类型最多能存10位,但最大值位2147483647,不是9999999999(long long同理)

  2. 因为之前在刷“欧拉计划”16题时有过用数组存高精度数据的经历,因为对这样的做法掌握的不是很透彻,没有搞清楚使用的情形,本以为这道题也要使用相同的思想。采用输入一个char类型的数组(或string类型),转化成int类型计算,但其实这样是矛盾的思想,违背了用数组求高精度基本思想(具体看”欧拉计划“笔记)。

    https://www.baidu.com/s?ie=UTF-8&wd=char%E7%B1%BB%E5%9E%8B%E8%BD%AC%E5%8C%96%E4%B8%BAint

    https://www.cnblogs.com/daleyzou/p/9510334.html

  3. 最后,对于输出格式也进行一个总结:

    C++使用cout输出不同考虑输出格式,若想使用C的输出方式printf则需要考虑(https://zhidao.baidu.com/question/525357989497186645.html),这也正是题目中所提示的那样

  4. 幂,阶乘


  1. 阶乘计算

image-20230228181947377

解法:枚举

关键字:高精度

#include<iostream>
using namespace std;
int main()
{
	int n;
	cin >> n;
	int A[10000] = { 0 };//全部初始化为0,防止进行阶乘时出现负数
	A[0] = 1;//因为要进行的是乘法,所以第一个数必须为1; 
	for (int i = 1; i <= n; i++)
	{
		int carry = 0;//目的,使得上次的相乘与现在无关(如2*3的进位与1*2的无关 ) 
		for (int j = 0; j < 10000; j++)
		{
			A[j] = A[j] * i + carry;
			carry = A[j] / 10;
			A[j] = A[j] % 10;
		}
	}
	int end;
	for (int i = 10000 - 1; i >= 0; i--)//判断出最后一位的下标,并记录 
	{
		if (A[i] != 0)
		{
			end = i;
			break;
		}
	}
	for (int i = end; i >= 0; i--)
	{
		cout << A[i];
	}
	return 0;
}

时间复杂度:O(n2)

思考过程:

  1. 一开始简单的认为是“欧拉计划的16题”修改语句,str[j]*=2; 变成str[j]*=i;即可,后来调试后发现,因为幂每次乘积不会扩大的量级跟阶乘还是有所不同,无法解决进位的问题。

    #include<bits/stdc++.h>
    using namespace std;
    
    int main(){
    	int str[400];
    	int i,j,n=0;
    	cin>>n;
    	for(i = 0; i < 400; i++)
    	//初始化 数组a[i]中每一项都为0
    	{
    		str[i] = 0;
    	}
    	str[0] = 1;
    	for(i = 1; i <= n ;i++)
    	{
    		for(j = 0;j < 400;j++)
    		{//数组的每一个数都乘i
    			str[j]*=i; 
    			if(str[j]>0){
    				cout<<j<<":"<<str[j]<<endl;
    			}
    		}
    		cout<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;
    		for(j = 0;j < 400;j++)
    		{//逢10进1
    			if(str[j] > 9)
    			{
    				str[j+1]=str[j]/10;
    				cout<<j<<":"<<"2j+1::"<<str[j+1]<<endl;
    				str[j] = str[j] % 10;
    				cout<<j<<":"<<"2j::"<<str[j]<<endl; 
    				cout<<"--------------------------------结束"<<endl; 
    //				cout<<str[j]<<endl;
    			}
    		}
    	}
    //	for(i = 399;i >= 0;i--){
    //		cout<<str[i];
    //	}
    	return 0;
    	
    } 
    
  2. 图解:

    https://blog.csdn.net/weixin_43906799/article/details/104751549

  3. 若不是高精度问题,求解阶乘问题可以用”递归“的方式进行求解


  1. 高精度加法

image-20220308214055100

解法:数学方法—高斯等差数列求和公式/枚举

关键字:高精度

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;