ZISUOJ C语言-函数

说明

博主是ZISU在校学生,刚学C/C++才2个多月,为了记录自己的学习过程和分享思路,故写一些博客。当然我的代码许多时候不是最优解,欢迎大家评论留言一起学习。如果有友友想提交这些题试试自己的思路啥的,可以私我,因为外校友友应该是登陆不进咱们的平台的。对于搜索到本博客的同校友友,切勿直接照抄,理解了再自己码字码上去。

题目列表

问题 A: 分段函数求解

思路:直接写,只不过这次把处理封装成一个自定义函数

 参考题解:

#include <iostream>
using namespace std;
int f(int x){
	if(x < 1) return x;
	else if(x < 10) return 2*x-1;
	else return 3*x-11;
}
int main(){
	//问题 A: 分段函数求解
	int x;cin >> x;
	cout << f(x) << endl;
	return 0;
}

问题 B: 最大公约数

思路:求最大公约数咱们这个阶段使用辗转相除法最优

 参考题解:

#include <iostream>
using namespace std;
int gcd(int x,int y){	//辗转相除法 
	int temp; 
	if(x < y){
		temp = x;
		x = y;
		y = temp;
	}
	while(x%y!=0){
		temp = x % y;
		x = y;
		y = temp;
	}
	return y;
}
int main(){
	//问题 B: 最大公约数
	int x,y;cin >> x >> y;
	cout << gcd(x,y) << endl;
	return 0;
}

问题 C: 最大公约数和最小公倍数

说明:最大公约数同上题,找最小公倍数可以通过最大公约数直接算出,但我这里使用了暴力寻找的方法

参考题解:

#include <iostream>
#include <cmath>
using namespace std;
int gcd(int x,int y){	//辗转相除法 
	int temp; 
	if(x < y){
		temp = x;
		x = y;
		y = temp;
	}
	while(x%y!=0){
		temp = x % y;
		x = y;
		y = temp;
	}
	return y;
}
int lcd(int x,int y){	//暴力寻找 
	for(int i = max(x,y);i<=x*y;i++) if(i%x==0&&i%y==0) return i;
} 

int main(){
	//问题 C: 最大公约数和最小公倍数
	int x,y;cin >> x >> y;
	cout << gcd(x,y) << " " << lcd(x,y) << endl;
	return 0;
}

问题 D: Goldbach's conjecture

思路:暴力寻找即可,其中需要写一个判断是否为素数的自定义函数

参考题解:

#include <iostream>
using namespace std;
bool is_Prime(int n){	//判断是否为素数 
	if(n == 1) return false;	//1不是素数 
	if(n == 2) return true;		//2为素数 
	for(int i = 2;i*i<=n;i++) if(n%i==0) return false;//如果有因子,则不是素数 
	return true;				//没有因子,则为素数 
}

int main(){
	//问题 D: Goldbach's conjecture
	for(int i = 4;i<=100;i+=2){
		cout << i << "=";
		for(int j = 2;j<i;j++){
			if(!is_Prime(j)) continue;	//若j不为素数则继续找 
			if(is_Prime(i-j)){			//如果j为素数且i-j也为素数,则输出 
				cout << j << "+" << i-j << endl;
				break;
			}
		}
	}
	return 0;
}

问题 E: 素数回文数的个数

思路:上一题已经写了判断是否为素数的自定义函数,这个题再加上写一个判断是否为回文数的函数即可。判断既是素数又是回文数则count++,最终输出count

参考题解:

#include <iostream>
using namespace std;
bool is_Prime(int n){		//判断是否为素数 
	if(n == 1) return false;
	else if(n == 2) return true;
	for(int i = 2;i*i<=n;i++) if(n%i==0) return false;
	return true;
}
bool is_Huiwen(int n){		//判断是否为回文数 
	int temp = n,sum = 0;	//左右颠倒数字判断是否相等 
	while(temp != 0){
		sum = sum*10 + temp %10;
		temp /= 10;
	}
	if(sum==n) return true;
	else return false;
}
int main(){
	//问题 E: 素数回文数的个数
	int n,count = 0;cin >> n;//count计数 
	//若找到既是素数又是回文数的,count加一 
	for(int i = 11;i<=n;i++) if(is_Prime(i)&&is_Huiwen(i)) count++; 
	cout << count << endl;
	return 0;
}

 问题 F: 判决素数个数

思路:同样也是遍历判断,注意这里写判断素数的自定义函数的时候,不要忘记输入的数可能是1和2,1和2一般要特殊处理

参考题解:

#include <iostream>
using namespace std;
bool is_Prime(int n){			//判断是否为素数 
	if(n == 1) return false;
	else if(n == 2) return true;
	for(int i = 2;i*i<=n;i++) if(n%i==0) return false;
	return true;
}
int main(){
	//问题 F: 判决素数个数
	int x,y,count = 0;cin >> x >> y;//count用于计数 
	for(int i = x;i<=y;i++) if(is_Prime(i)) count++;
	cout << count << endl; 
	return 0;
}

问题 G: digit函数 

 

 思路:注意题目是从右往左找,直接循环整除10找即可

参考题解:

#include <iostream>
using namespace std;
int find(int n,int k){	//实现找digit的函数 
	int count = 1,temp = n;//count初始化为1,count代表从右往左第count个数字 
	while(temp != 0){
		if(count == k) return temp%10;//先判断count是否等于k,count再++ 
		count++;
		temp /= 10;
	}
}
int main(){
	//问题 G: digit函数
	int n,k;cin >> n >> k;
	cout << find(n,k) << endl;	//函数调用 
	return 0;
}

问题 H: 小数化分数1

相对其他题来说比较难,这里给出两种思路

思路1:以字符串形式读入小数,然后从小数点后开始构造分子和分母,特别地,此处后续对分子分母的约分直接调用头文件<algorithm>的__gcd()函数用于求最大公约数,其实像前面的题一样写一个gcd()函数也很快的

 参考题解1:

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
char ch[12];
void transform(){
	int fenzi = 0, fenmu = 1;
	cin >> ch;
	for(int i = 2;i<strlen(ch);i++) {
		if (ch[i] >= '0' && ch[i] <= '9') {
			fenmu *= 10;			//构造分母 
			fenzi = fenzi * 10 + ch[i] - '0';//构造分子 
		}
	}
	if (fenmu == 10 && fenzi == 0) {//如果输入0.0则输出0/1
		cout << "0/1" << endl;
		return;
	}
	//找最大公约数约分
	int _gcd = __gcd(fenmu,fenzi);
	fenmu = fenmu / _gcd;
	fenzi = fenzi / _gcd;
	cout <<	fenzi << "/" << fenmu << endl;
}
int main() {
	//问题 H: 小数化分数1
	int n;
	cin >> n;
	getchar();//读掉最后的换行符
	while(n--) transform();
	return 0;
}

思路2:以双精度浮点数double的形式读入数据,根据题意小数位不会超过9位,构造分母为1e9,构造分子为数据乘以1e9,但是注意此处分子的构造会丢失精度,需要在乘以1e9后再加上0.5解决精度丢失问题,然后约分输出即可

参考题解2:

#include <iostream>
using namespace std;
int gcd(int x,int y){	//求最大公约数函数 
	int temp;
	if(x<y){			//确保x>y 
		temp = x;
		x = y;
		y = temp;
	}
	while(x%y != 0){	//辗转相除法求最大公约数 
		temp = x%y;
		x = y;
		y = temp;
	}
	return y;
}
int main(){
	//问题 H: 小数化分数1
	int n;cin >> n;
	double dec;
	int num;
	while(n--){
		cin >> dec;
		num = dec*1000000000+0.5;	//+0.5是为了解决精度丢失的问题 
		if(num==0) cout << "0/1" << endl;//num为0输出“0/1” 
		else{
			int gcdnum = gcd(1000000000,num);//找num和1e9的最大公约数 
			cout << num/gcdnum << "/" << 1000000000/gcdnum << endl; //输出的时候,分子分母同时除以最大公约数 
		}
	}
	return 0;
} 

问题 I: 字符串匹配 

 

又算一个难题,难点在字符匹配这一个阶段

思路:操作1比较好处理,注意刚开始给buf[]数组长度时尽可能大一些,将两个字符串通过下标(索引)拼接;操作3是最好处理的,我们都知道数组遇到'\0'会认为已经到头了,我们只需计算数组buf长度与len的差,直接找到对应下标,修改值为'\0';操作2是匹配字符串,最好写一个函数,我这里匹配的思路是暴力匹配

参考代码:

#include <iostream>
#include <cstring>
using namespace std;
int lenbuf,lens;
void match(char buf[10005],char s[105]){	//字符串匹配 
	lenbuf = strlen(buf);lens = strlen(s);
	int maxk = 0;
	for(int i = 0;i<lenbuf;i++){			//暴力匹配 
		for(int j = 0;j<lens;j++){
			int k;
			for(k = 0;k<lens;k++){			//如果buf[i+k]和s[j+k]对应都相等,k++
				if(buf[i+k] != s[j+k]) break;
				if(buf[i+k] == '\0') break;
			}
			if(k > maxk) maxk = k;		//求出所有k中最大的那个k,就是我们要找的值 
		}
	}
	cout << maxk << endl;
}
int main(){
	//问题 I: 字符串匹配
	char buf[10005],s[105];
	int m,op,len;
	while(~scanf("%s",buf)){//~scanf() 等价于 scanf()!=EOF 也等价于 scanf() == 1 
		cin >> m;
		while(m--){
			cin >> op;		//op为操作数:1或2或3 
			if(op == 1){
				lenbuf = strlen(buf);
				cin >> s;
				lens = strlen(s);
				for(int i = 0;i<lens;i++) buf[lenbuf+i] = s[i];//拼接字符串 
				buf[lenbuf+lens] = '\0';//找到buf的新长度,输入结束符'\0' 
			}else if(op == 2){
				cin >> s;
				match(buf,s);			//调用函数 
			}else if(op == 3){
				cin >> len;
				lenbuf = strlen(buf);
				buf[lenbuf-len] = '\0';	//直接用结束符'\0'截断即可 
			}
		}
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Beau_Will

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值