计导实验五

C. 圆的切分

运行时间限制: 1000 运行内存限制: 65536
作者: scsyuanbaoku 是否specialjudge: False
题目描述
在一个平面上有一个圆和n条直线,这些直线中每一条在圆内同其他直线相交,假设没有3条直线相交于一点,试问这些直线将圆分成多少区域。
输入:
只有一个整数n(0<=n<100)。
输出:
只有一个整数,为圆被n条直线分成的区域的块数。
还是想放上这个题,记得高中上数学课讲到这个时还是很懵的,另外,我是会用递推式的人

#include<stdio.h>
int f(int i)
{
	if(i==0)return 1;
	else return i+f(i-1);
}
int main()
{
	//每与一条直线相交就会多一块,与轮廓相交多一块,第n条直线,多n块 
	int n;
	scanf("%d",&n);
	printf("%d\n",f(n));
	return 0;
}

D. 韩信点兵

运行时间限制: 1000 运行内存限制: 65536
作者: scsyuanbaoku 是否specialjudge: False
题目描述
韩信有一队兵,他想知道一共有多少人,便让士兵排队报数。站5人一排,多出1人;站6人一排,多出5人站;7人一排,多出6人;站11人一排,多出10人。问韩信至少有多少兵?

输入:
为一个整数n(0<n<10000)。
输出:
一个不小于n的整数,为韩信可能拥有兵的数量的最小值。
说说这个韩信点兵,我小时候是真不聪明啊。那个时候听到这类的问题就不怎么明白,现在懂了。有个口诀,加同补(补数,除数减余数)加上补数就能得最小公倍数,减同余,减掉相同的余数就能得到最小公倍数。代码如下

#include<stdio.h>
int main()
{
	int n,i,bing;
	scanf("%d",&n);
	for(i=1;;i++)
	{
		bing=6*7*11*i-1;
		if(bing%5==1&&(n<=bing))//用满足6,7,11的数作为基础,等号很重要
		{
			printf("%d\n",bing);break;
		}
	}
	return 0;
} 

E. 实验4_15_进制转换2

运行时间限制: 1000 运行内存限制: 65536
作者: bupt_admin 是否specialjudge: False
题目描述
问题描述:
你的任务是实现带小数的二进制数到十进制数的转换。二进制字符序列以字符“#”结尾,如“1011.101#”。将二进制数“1011.101”转换为十进制数的过程如下:
(1101.101)2=123+0*22+121+1*20+12{-1}+0*2{-2}+12^{-3}=(11.625){10}(1101.101)
​2
​​ =1∗2
​3
​​ +0∗2
​2
​​ +1∗2
​1
​​ +1∗2
​0
​​ +1∗2
​−1
​​ +0∗2
​−2
​​ +1∗2
​−3
​​ =(11.625)
​10
​​
二进制字符序列中只可能存在“0”、 “1”、 “.”、 “#”四种字符,不会出现任何其他字符。为了提高结果的精度,建议使用double类型的变量存储结果。

输入与输出要求:
输入一个以“#”结尾的字符序列,代表待转换的二进制数。输出转换后的十进制数,如果二进制数有小数部分,则输出结果保留6位有效数字;如果二进制数没有小数部分,则输出结果中没有小数点和小数部分。

程序运行效果:
Sample 1:
11001.0110#↙
25.375000↙
Sample 2:
1101#↙
13↙
在这个题上遇到了许多困难:
1、数据存储问题。最终还是采用了字符数组,因为它能存储数字、小数点和井号
2、如何将拆开的位数分别乘以它应乘的2的次方。这里利用’.'与
'#'号的位置,用循环将最大的算出来,依次除以2.
3、字符ascii码与本值的关系。一开始直接用a[i]去乘,得到超级大的数,后来才发现数字应减48才得本值。
4、浮点数与整型的变换。这点没注意,以致得到的结果一直没加小数点后的值。
下面是AC代码

#include<stdio.h>
int main()
{
	char a[32];
	int i,xsd=0,jh,gs=1;
	scanf("%s",&a);//输入存储问题
	//找到小数点,井号 
	//printf("%s\n",a);
	/*double a;
	scanf("%lf",&a);//没读到井号 
	printf("%lf\n",a);*/
	//char a[32];
	for(i=0;;i++)
	{
		if(a[i]=='.')xsd=i;//对'.'与'#'号的位置存储
		if(a[i]=='#')
		{
			jh=i;break;
		}
	}
	//printf("%d %d\n",xsd,jh);
	if(xsd==0)
	{
		for(i=jh-1;i>0;i--)//将最高位要乘地2的次方计算出来 
		{
			gs*=2; 
		}
		//printf("%d\n",gs);
		int sum=0;
		for(i=0;i<jh;i++)
		{
			sum+=(a[i]-48)*gs; //拿来做运算的是字符的ascii码,所以减48才是它的本值
			gs/=2; 
		}
		printf("%d\n",sum);
	}
	else
	{
		double sum=0,gs2=2;
		for(i=xsd-1;i>0;i--)
		{
			gs*=2; 
		}
		//printf("%d\n",gs);
		for(i=0;i<xsd;i++)
		{
			//printf("%d\n",a[i]);
			//printf("%d\n",a[i]*gs);
			sum+=((a[i]-48)*gs); 
			gs/=2; 
			//printf("%.6f\n",sum);
		}
		for(i=xsd+1;i<jh;i++)
		{
			//printf("%d\n",a[i]);
			sum+=((a[i]-48)/gs2);
			gs2*=2;//在gs2是整型的情况下,此处不能乘2,应乘2.0以得到浮点数,不然,上式全部加的都是0,sum值无法改变 ;在gs2是浮点数的情况下,乘2可得浮点数 
			//printf("%.6f\n",sum);
		}
		printf("%.6f\n",sum);
	}
	return 0;
}

G. 三角形

运行时间限制: 1000 运行内存限制: 65536
作者: scsyuanbaoku 是否specialjudge: False
题目描述
有一根绳子的长度为n(3<=n<1000且为整数),将该绳子分成三段,每段的长度为正整数,输出由该三段绳子组成的三角形个数。

输入样例
3
输出样例
1
看到这个题简单朴素的想法是循环,先来个三重循环

#include<stdio.h>
int main()
{
	int n,i,j,k,sum=0;
	scanf("%d",&n);
	for(i=1;i<=n/3;i++)//此处取n/3,因为下面j=i,k=i,之后再循环无意义 
	for(j=i;j<n;j++)//这样写之后出现的数字都是后一位不会小于前一位,保证了循环的不重复 
	for(k=j;k<n;k++)//如何让重复的结果消失? (见上)
	{
		if((i+j+k==n)&&(i+j>k)&&(i+k)>j&&(k+j)>i)
		{
			sum++;
			//printf("%d %d %d\n",i,j,k);
		}
	}
	printf("%d\n",sum);
	return 0;
} 

寻找更简单的算法如下

#include<stdio.h>
int main()
{
	int n,i,j,sum=0;
	scanf("%d",&n);
	for(i=1;i<=n/3;i++)//此处取n/3,因为下面j=i,k=i,之后再循环无意义 
	for(j=i;j<n;j++)//这样写之后出现的数字都是后一位不会小于前一位,保证了循环的不重复 
	if(n-i-j>=j)//将i+j+k=n,与第三重循环融在一起。当n-i-j<j时情况与前重复 
	if((i+j)>(n-i-j)&&(i+n-i-j)>j&&(j+n-i-j)>i)
	sum++; 
	printf("%d\n",sum);
	return 0;
} 

在这里插入图片描述
在开始下题之前先插入一个关于乘方运算的程序

#include<stdio.h>
#include<math.h>
int main()
{
	int c;
	scanf("%d",&c);
	printf("%d\n",2^c);//机器看不懂乘方运算 
	double a = pow(2, 10); // a等于2的10次方
	printf("%lf\n",a); 
	return 0;
}


输入c=0并没有得到2的0次方,下面这个才是正宗的乘方运算

I. 实验4_3_回文数

运行时间限制: 1000 运行内存限制: 65536
作者: bupt_admin 是否specialjudge: False
题目描述
问题描述:
回文是指正读和反读都一样的数或文本段。例如,12321、55555、45554、11611都是回文数。输入一个长度不超过10位的整数n,判断它是否是回文数。

输入与输出要求:
输入一个整数n,即待判断的数字。当n为回文数时输出“Yes”,否则输出“No”。

程序运行效果:
Sample 1:
12321↙
Yes↙
Sample 2:
126521↙
No↙
以下代码的思路为,将该数首位与末位摘出来逐一比较,如果相等,将首位与末位去掉,重新比较新的首位与末位

#include<stdio.h>
int main()
{
	int n,chushu=1,t1,t2,weishu=1,i,j,pd=1;
	scanf("%d",&n);
	//取出位数
	j=n/10;
	t1=n;
	t2=n;
	if(j==0)//只有一位 
	{
		printf("Yes\n");
		return 0;
	}
	while(j!=0) 
	{
		n/=10;
		j=n/10;
		chushu*=10;
		weishu++;//引入位数限定循环范围
	}
	//printf("%d\n",weishu);
	for(i=1;i<=weishu/2;i++)
	{
		//printf("%d %d\n",(t1/chushu)%10,t2%10);
		if((t1/chushu)%10==t2%10)//用于获取首位与末位
		{
			chushu/=10;
			t2/=10;
		}
		else 
		{
			pd=0;printf("No\n");break;
		}
	}
	//printf("Yes\n");这句不能放在这里 
	if(pd==1)printf("Yes\n");//需要加一个变量作为判断
	return 0;	
}

更简单的思路是,直接将整个数倒过来与原数比较,若相等,即为回文数。

#include<stdio.h>
int main()
{
	int n,weishu,daoshu=0,cfs=1,t,t1;
	scanf("%d",&n);
	t=n/10;
	t1=n;
	while(t!=0)
	{
		cfs*=10;
		t/=10; 
	} 
	while(n!=0)
	{
		weishu=n%10;//这里是尾数
		daoshu+=weishu*cfs;
		n/=10;
		cfs/=10;
	}
	//printf("%d %d\n",daoshu,t1); 
	if(daoshu==t1)printf("Yes");
	else printf("No");
	return 0;
} 

这个方法求颠倒的数还是复杂,体现在仍然用了一个循环专门来求出从尾数变成最高位需要乘的10的次方(以上两个都有)吸取他人做法之后,得到改良后的代码

#include<stdio.h>
int main()
{
	int n,s,daoshu=0;
	scanf("%d",&n);
	s=n;
	while(s>0){
		daoshu=daoshu*10+s%10;
		s/=10;
	}
	if(daoshu==n)printf("Yes");
	else printf("No");
	return 0;
}

一些关于随机数的验证

#include<stdio.h>
#include<stdlib.h>

int main()
{
	int i;
	
	for(i=1;i<=20;i++)
	{
	  printf("%10d",rand());
	  if(i%5==0)
	    printf("\n");
	}
	//printf("%d\n",1+rand()%6); 一次产生一个 
	//printf("%d\n",0xfffff); 
	return 0;
}

如脱缰的野马般大
数字很大,产生限定范围内的随机数:从X到Y,有Y-X+1个数,所以要产生从X到Y的数,只需要这样写:

k=rand()%(Y-X+1)+X; 或k=X+rand()%(Y-X+1);

以下是完整代码

#include<stdio.h>
#include<stdlib.h>
#include<time.h>//以时钟做种子 
int main()
{
	int i,seed;
	srand(time(NULL));
	/*scanf("%d",&seed);//自己输入种子以控制随机数 
	srand(seed);*/
	for(i=1;i<=20;i++)
	{
	  printf("%10d",0+rand()%6);//1+rand()%x,产生1到x的随机数 
	  if(i%5==0)
	    printf("\n");
	}
	//printf("%d\n",1+rand()%6); 一次产生一个 
	//printf("%d\n",0xfffff); 
	return 0;
}

H. 实验3_B_小学奥数题

运行时间限制: 1000 运行内存限制: 65536
作者: scshuanghai 是否specialjudge: False
题目描述
上小学四年级的小王同学虽然很笨,但他非常喜欢钻研奥数题。他遇到了这样的一个计算分数的问题:S(n)=1/3+3/5+5/7+…+n/(n+2),n为小于40的奇数。题目要求根据n来计算S(n)的值。他苦思冥想也没找出规律来解这道题,其实这道题目根本就没有规律,是老师用来难为不听话的学生用的。小王同学知道了实情后仍然不放弃去解这道题。当n值很大时,用纸笔计算非常费力,用计算器也很麻烦,有的计算器也不能计算分数。现在他只能求助你来编程帮他实现计算S(n)了,注意S(n)的计算结果应为分数形式。

输入与输出要求:
输入一个整数n,n的范围是1—40,且为奇数。输出S(n)的计算结果,如输出S(3)的结果:“14/15”。

程序运行效果:
Sample 1:
7↙
764/315
Sample 2:
21↙
2861599189/334639305
Sample 3:
39↙
116320091982737732/6845630929362225
看到这题样例的时候就应该想到,用int型会溢出,换类型的时候输入输出格式符也应该换。这题还用到了求最小公倍数。(1h10多分才写出来)

//注意S(n)的计算结果应为分数形式
#include<stdio.h>
long long fenmu=1;
void zxgbs(int i)//最小公倍数 
{
	//表示分母;寻找分母最小公倍数,参照之前的代码
	//多个数的最小公倍数?循环迭代?
	long long t,t1,t2,j;
	t1=fenmu;t2=i;//t2寄存i值 
	if(t1<i)t=i,i=t1,t1=t;
	j=t1%i;
	if(j==0)fenmu=t1;
	else
	{
		while(j!=0)//求上级最小公倍数与此级的最小公倍数 
		{
			t1=i;i=j;j=t1%i;
		}
		fenmu=fenmu/i*t2;//此处t2应是未发生变化时的i 
	}
	//printf("%d\n",fenmu);
}
int main()
{
	int n,i;//分子只需乘对应分母到公倍数所乘的数 
	long long fenzi=0;
	scanf("%d",&n);
	//s(n);
	for(i=3;i<=n+2;i+=2)
	{
		zxgbs(i);	
	}//接下来处理分子
	for(i=3;i<=n+2;i+=2)
	{
		//printf("%d") 
		fenzi+=((fenmu/i)*(i-2));
		//printf("%lld\n",fenzi);//分子溢出? 
	}
	//printf("%d\n%d\n",fenzi,fenmu);
	printf("%lld/%lld\n",fenzi,fenmu);
	return 0;	
} 

F. 实验4_20_牛顿迭代法

运行时间限制: 1000 运行内存限制: 65536
作者: bupt_admin 是否specialjudge: False
题目描述
问题描述:
在这里插入图片描述
注意:建议浮点数用double存储,用float精度可能不够。

输入与输出要求:
输入四个正整数a、b、c、d,代表方程的系数。输出方程在1附近的一个实根,占一行。

程序运行效果:
Sample 1:
1 3 5 2↙
-0.546602↙
Sample 2:
12 34 25 30↙
-2.399306↙
我以为这题很难,把它留到了最后,然而,10多分钟(近二十分钟)就写完。难道这题的实质是把公式表达出来?另外,如何判断它与真实值更接近?

#include<stdio.h>
#include<math.h>
int main()
{
	int a,b,c,d;
	double xn=1,xn1;
	scanf("%d%d%d%d",&a,&b,&c,&d);
	//导数方程
	while(1)
	{
		double daoshu=3*a*xn*xn+2*b*xn+c;
		double hanshu=a*xn*xn*xn+b*xn*xn+c*xn+d;
		xn1=xn-(hanshu/daoshu);
		if(fabs(xn1-xn)<=1e-5)
		{
			printf("%.6lf",xn1);break;
		}
		else xn=xn1;
	}
	
	return 0; 
}

可参考原创博主:马同学高等数学 如何通俗易懂地讲解牛顿迭代法?

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值