湘潭大学-2023年下学期-c语言-作业0x0a-综合1

A 求最小公倍数

cpp 复制代码
#include<stdio.h>

int gcd(int a,int b)
{
	return b>0?gcd(b,a%b):a;
}

int main()
{
	int a,b;
	while(~scanf("%d%d",&a,&b))
	{
		if(a==0&&b==0)	break;
		
		printf("%d\n",a*b/gcd(a,b));
	}
	
	return 0;
}

记住最大公约数的函数,然后最小公倍数等于两个数的乘积除以最大公约数,最大公约数函数是代码中的gcd函数

B 爱你一生一世

cpp 复制代码
#include<stdio.h>

int gcd(int a,int b)
{
	return b>0?gcd(b,a%b):a;
}

int main()
{
	int k;
	scanf("%d",&k);
	
	while(k--)
	{
		int n,m;
		scanf("%d%d",&n,&m);//礼物的件数和不喜欢的礼物的件数
		
		if(m<2)	printf("1\n");
		else if(n==m)	printf("0\n");
		else
		{
			int a=(n-1)*n-(m-1)*m;
			int b=n*(n-1);
			int temp=gcd(a,b);
			a/=temp;
			b/=temp;
			printf("%d/%d\n",a,b);
		}
	}
	
	return 0;
}

这道题我非常感慨,因为以前对我来说确实是拦路虎,现在确实可以轻松写出来了

应用最大公约数函数,分式计算的话,就是分子分母同时除以最大公约数,如果分母等于1 ,就只需要输出分子

该题还需要推一下公式,选两件不同的礼物,至少有一件礼物是她喜欢的,反面是没有一件礼物是她喜欢的,用1减去反面的概率,就是我们要求的概率,很明显,反面的概率更容易求

公式如上,不喜欢的礼物数目小于2的话,选两件礼物,一定至少有一件礼物是她喜欢的,所以概率是1,如果所有礼物她都不喜欢,概率就是0(想起来,网上一个段子,她不是不喜欢这件礼物,只是不喜欢你哈哈)

甚至都不需要判断分母是否等于1,因为分母不可能等于1,如果分母等于1,只有一种情况,就是答案为1,但是答案为1的情况我们已经特判过了

C 奇偶校验

cpp 复制代码
#include<stdio.h>
#include<string.h>

int main()
{
	int n;
	while(~scanf("%d",&n))
	{
		if(n==-1)	break;
		
		int a[10];
		for(int i=1;i<=8;i++)
		{
			a[i]=n%2;
			n/=2;
		}
		
		//for(int i=8;i>=1;i--)	printf("%d",a[i]);
		
		int cnt=0;
		for(int i=8;i>=2;i--)
		{
			if(a[i]==1)
			{
				cnt++;
			}
		}
		
		int b=0;
		if(cnt%2==0)	b=0;
		else	b=1;
		
		if(b==a[1])	printf("Yes");
		else	printf("No");
		
		printf("\n");
		
		memset(a,0,sizeof a);
	}
	
	return 0;
}

进制转换的一道题目,对进制取模,然后除以进制,非常经典,记住这个讨论即可

注意这里下标是从0开始的(题干里面),所以我一开始还是非常奇怪的,为什么只算前面六位当数据位,原来从0开始数数到六是七位

思路就是把一个十进制数字转换成二进制数字,把每一位数字存在数组里面,然后根据题目要求模拟一下即可

D n!进制

cpp 复制代码
#include<stdio.h>

int a[15];

void fact()
{
	a[0]=1;
	a[1]=1;
	
	for(int i=2;i<=15;i++)	a[i]=a[i-1]*i;
}

int main()
{
	fact();
	
	int n;
	while(~scanf("%d",&n))
	{
		if(n==0)	
		{
			puts("0");
			continue;
		}
		
		int temp=0;
		for(int i=15;i>=1;i--)	
		{
			if(a[i]<=n)	
			{
				temp=i;
				break;
			}
		}
		
		while(temp!=0)//最小是到1的阶乘
		{
			int ans=n/a[temp];
			printf("%d",ans);
			n%=a[temp];
			temp--;
		}
		
		puts("");
	}
	
	return 0;
}

不知道是什么原因,挺难理解这个题目的意思的

题目的意思是说,给定一个十进制数字,要求我们输出这个十进制数字的n!进制数字。这个定义比较奇怪,光看题干的21的例子,我还以为是把数位上的数字乘以该数字的阶乘,然后累加,累加的结果就是答案

但是事实上,10按照这个思路应该是1,100按照这个思路也是1,但是样例分别是120和4020

权重乘以系数就是总共的大小,观察一下数据范围,数据范围是3628799,这个数字是10的阶乘减去1,权重乘以系数,表示数字大小,每一位上的系数,从高位一直输出到最低位就是答案

要优先处理最高位,因为权重最大,假设优先处理最低位,很有可能会导致系数非常大,与实际情乱矛盾

所以思路就是,找到比当前十进制数字小的最大的阶乘,然后除以该阶乘,表示的是最高位的系数,输出这个系数,十进制数字n对该阶乘取余,表示的是剩下的数字的大小,然后把阶乘变成下一个阶乘(比如说4的阶乘变成3的阶乘,3的阶乘变成2的阶乘),一直到阶乘是1的阶乘,表示操作结束,输出换行即可

在循环里我们除了使用 if 这种条件判断,还可以使用 continue 表示后面的都不考虑,直接下一次循环,也非常方便

前面的 fact 函数是用来求阶乘的,fact是 factorial 英文的前四个字母,表示阶乘

另外发现写c语言题目还是用 c 语言比较友好,不然我辛苦写却不符合学弟学妹的需求,还是有点无奈的哈哈

笔者都大二了,还是不能随手秒掉这些 c语言题目,还是非常惭愧啊

E ICPC

cpp 复制代码
#include<stdio.h>
#include<string.h>

char s1[110],s2[110],s3[110];
int cnt[10];

int main()
{
	int n;
	while(~scanf("%d",&n))
	{
		if(n==0)	break;
		
		scanf("%s",s1+1);
		scanf("%s",s2+1);
		scanf("%s",s3+1);
		
		char ans;
		for(int i=1;i<=n;i++)
		{
			ans=s1[i];
			if(s2[i]<ans)	ans=s2[i];
			if(s3[i]<ans)	ans=s3[i];
			
			printf("%c",ans);
			
			cnt[ans-'A'+1]++;
		}
		printf("\n");
		
		for(int i=1;i<=4;i++)	printf("%d ",cnt[i]);
		printf("%d\n",cnt[5]);
		
		memset(cnt,0,sizeof cnt);
	}
	
	return 0;
}

算是简单的数组的使用

主要问题是空格......

还有就是不用c++的min函数确实写起来不是很熟练

输入字符的时候,空格也会读入,所以非常不方便,所以还是用字符串读入比较好,然后计数器数组每一次循环之后要重置,不然会影响下一次循环的结果

题目需要模拟的就是输入的数据里面,每一列的最小的字母,输出这个字母,然后给这个字母计数即可,注意输出的格式,防止PE

F coins

cpp 复制代码
#include<stdio.h>

int dp[45][2];

int main()
{
	dp[1][0]=1;//正面
	dp[1][1]=1;//反面
	
	for(int i=2;i<=40;i++)
	{
		dp[i][0]+=dp[i-1][1];
		dp[i][1]+=(dp[i-1][0]+dp[i-1][1]);
	}
	
	int n;
	while(~scanf("%d",&n))
	{
		if(n==0)	break;
		
		printf("%d\n",dp[n][0]+dp[n][1]);
	}
	
	return 0;
}

做不出来,简单的动态规划题目......

不包含连续的正面的方案数目。意思就是,只能是全部是反面,正反交替,或者是反面+正反交替

本来以为正面不好枚举答案,然后发现反面也不好枚举答案

DP来做这题,首先是DP集合表示什么意思,第一维表示的是有多少个硬币,第二维表示的是正面或者反面两种情况,我们需要做的是枚举所有情况

状态计算的时候,0表示正面,正面前面可以放反面

1表示反面,反面前面任意放

代码很短,但是得有动态规划的思路,才能做出来

G 因子和

cpp 复制代码
#include<stdio.h>

int main()
{
	long long n;
	while(~scanf("%I64d",&n))
	{
		if(n==0)	break;
		
		long long ans=0;
		for(int i=1;i*i<=n;i++)
		{
			if(n%i==0)
			{
				if(i==n/i)	ans+=i;
				else	ans+=i+n/i;
			}
		}
		
		printf("%I64d\n",ans);
	}
	
	return 0;
}

第一眼以为是前缀和,求1到n所有数字的和

直接按照题意模拟,用%lld输出,超时了,改成%I64d就过了

正解应该是要用算数基本定理的推论去分解质因数,然后套用公式求解

如果两个因子相等表示该数字是一个完全平方数,该因子只能被计算一次,如果不是的话就可以计算两次,分界点是输入的数字开根号

结语

总结就是,我感觉我C语言期末考试要爆零了,感觉一个题都做不来,慌......

相关推荐
isyangli_blog1 小时前
OpenDayLight (Carbon 版本) 启动与组件安装
开发语言·php
vb2008111 小时前
FastAPI APIRouter
开发语言·python
Benszen2 小时前
KVM虚拟化解决方案
开发语言·perl
会编程的土豆2 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
東雪木2 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
杨充2 小时前
1.3 浮点型数据设计灵魂
开发语言·python·算法
噜噜噜阿鲁~2 小时前
python学习笔记 | 11.3、面向对象高级编程-多重继承
java·开发语言
basketball6162 小时前
Go 语言从入门到进阶:4. 数组和MAP使用方法总结
开发语言·后端·golang
春生野草3 小时前
反射、Tomcat执行
java·开发语言
雪的季节4 小时前
企业级 Qt 全功能项目
开发语言·数据库·qt