2023东华大学OJ机试题22-70

22 约瑟夫环2

#include <stdio.h>

//解法一:一维数组构造循环顺序表
int solution1(int *num, int n, int x)
{
    int dieout = 0,index = 0;//dieout:目前已被淘汰的人数index:移动指针
    while(dieout < n)
    {

        index = (index + x) % (n - dieout);
        if(num[index] <= n / 2 && dieout < n / 2)
        {
            return 0;
        }
//        把淘汰的人后面的都往前移一位
        int i = index + 1;
        while(i < n - dieout) {
            num[i - 1] = num[i];
            i++;
        }
        dieout++;
    }
    return 1;
}


int main()
{
    int k;
    while(scanf("%d",&k)!=EOF)
    {
        //    初始化一维数组
        int num[21] = {0};
        for(int i = 0; i < 2*k; i++)
        {
            num[i] = i + 1;
        }
        for(int m = 1;;m++)
        {
            if(solution1(num,k*2,m)==1)
            {
                printf("%d\n",m+1);
                break;
                }
        }
    }
    return 0;
}


23、整除的尾数

题目描述:一个整数,只知道前几位为a,不知道末二位,被另一个整数b除尽了,那么该数的末二位该是什么呢

思路:属于循环类型的题目,对整数a乘以100,然后加上0-99,依次判断,如果被整数b除尽,则输出,否则继续循环。注意题目要求结果前后无空格。

#include<iostream>
using namespace std;

int main() {
	int T,a,b; 
	cin>>T;
	while(T!=0){
		cin>>a>>b;
		int num=a*100; 
                int count=0;//count用来计数,保证结果前后无空格
		for(int i=0;i<100;i++){
			if((num+i)%b==0)//如果能整除b,则输出
				if(count==0)
                              {
                                   cout<<i;
                                  count++;
                                }
                               else
                               {
                                     cout<<" "<<i;
                               }
		}
		T--;
		cout<<endl; 
	}
	return 0;
}
 

24、回文质数

题目描述:因为151既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 号是回文质数。写一个程序来找出范围[a,b](5<= a < b <= 100,000)间的所有回文质数。

思路:编写两个函数,一个判断是否为质数,另一个判断是否为回文

#include<iostream>
#include<cmath>
using namespace std;

bool isPrime(int n) {//判断是否为质数
	int q;
	for(q = 2; q <= sqrt(n); q++) {
		if (n % q == 0) {//如果能够被整除,说明不是质数
			return false;
		}
	}
	if (q > sqrt(n)) {
		return true;
	}
}

bool isSys(int n) {
	int i = 0;
	int j = 0;
	int k = n;
	while(true) {
		j = j * 10 + k % 10;//j是n反转后的数字
		k = k / 10;
		if (k < 1) {
			break;
		}
	}
	if (j == n) {//如果n和反转后的数字相等,说明该数字是回文
		return true;
	} else {
		return false;
	}
}

int main() {
	int a, b;
	cin >> a >> b;
	for (int i = a; i < b; i++) {
		if(isSys(i)) {
			if(isPrime(i)) {
				cout<< i <<endl;
			}
		}
	}
	return 0;
}


25、汽水瓶

题目描述:有这样一道智力题:“某商店规定:三个空汽水瓶可以换一瓶汽水。小张手上有十个空汽水瓶,她最多可以换多少瓶汽水喝?”答案是5瓶,方法如下:先用9个空瓶子换3瓶汽水,喝掉3瓶满的,喝完以后4个空瓶子,用3个再换一瓶,喝掉这瓶满的,这时候剩2个空瓶子。然后你让老板先借给你一瓶汽水,喝掉这瓶满的,喝完以后用3个空瓶子换一瓶满的还给老板。如果小张手上有n个空汽水瓶,最多可以换多少瓶汽水喝?

注意:当小张手中还有两个瓶子的时候可以向老板借一瓶。

思路:属于循环类型的题,首先判断小张手里的瓶子数,如果为0,1,2则直接输出结果。否则另外判断

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

//当最后只有两瓶的时候老板可以借给你一瓶,用count存储可以换回来的瓶子数,用sum存储喝的汽水数
int main(int argc, char *argv[]) {
	int n,count,sum;
	while(scanf("%d",&n)!=EOF){
		if(n==0){
			return 0;
		}
		count=sum=0;//sum是小张可以换的汽水瓶的总数
		if(n==1){
			printf("0\n");
		}else if(n==2){
			printf("1\n");
		}else{
			while(n!=1){ //循环判断瓶子数
				if(n==2){//如果最终还剩两瓶,向老板借一瓶,总数加1
					++sum;
					break;
				}
				count=n/3;
				sum+=count;
				n=(n%3)+count;//除以3后还剩余的瓶子数
			}
			printf("%d\n",sum);
		}
	}
	return 0;
}

26、阶乘最后的非0位

题目描述:N的阶乘写作N!表示小于等于N的所有正整数的乘积。阶乘会很快的变大,如13!就必须用32位整数类型来存储,70!即使用浮点数也存不下了。你的任务是找到阶乘最后面的非零位。举个例子,5!=12345=120所以5!的最后面的非零位是2,7!=1234567=5040,所以最后面的非零位是4。

思路:属于循环类型的题,当阶乘很大时,可以舍弃前面的几位

#include<iostream>
#include<cmath>
using namespace std;

int main()
{
int n;
long sum=1,i;
while(cin>>n)
{
  for (i = 1; i <= n; i++) {
   sum*=i;
   while(sum%10==0)//如果阶乘末尾为0,则一直除以10
   {
     sum/=10;
   }
   sum=sum%1000;//防止数字过大
}
cout<<sum%10<<endl;
}
return 0;
}

27、算菜价

题目描述:妈妈每天都要出去买菜,但是回来后,兜里的钱也懒得数一数,到底花了多少钱真是一笔糊涂帐。现在好了,作为好儿子(女儿)的你可以给她用程序算一下了,呵呵。

思路:属于循环类型题目,依次将不同菜的数量和单价相乘,然后相加

#include<iostream>
#include<cmath>
#include<iomanip>

using namespace std;

int main()
{
	int n, m, i, j;
	double num, price, sum;
	while(cin>>n) {
		for	(i = 0; i < n; i++) {
		int x;
		scanf("%d",&x);
		double sum=0;//最终的开销
		while(x--)
		{
			//中文菜名用数组输入。
			char a[10];
			double b,c;
			//数组用%s,double用%lf
			scanf("%s %lf %lf",a,&b,&c);
			sum+=(b*c);
		}
		printf("%.1f\n",sum);		
		}
	}
	return 0;
}

28、 水果价格

题目描述:一家水果店出售四种水果,每公斤价格的苹果(代码为a)1.5元,橘子(代码为o)1.4元,香蕉(代码为b)1.48元,菠萝(代码为p)1.08元。编一个程序,使售货员只要在键盘上打入货品的代码及重量,计算机将显示货品名、单价、重量及总价。

思路:题目简单,主要要输出的规格要求有点麻烦

#include <iostream>
using namespace std;
int main()
{
	int m;
	char d;
	double g;
	while(scanf("%d",&m)!=EOF)
	{
		double sum1=0,sum2=0;
		double weight[4]={0};
		double price[4]={0};
		for(int i=0;i<m;i++)
		{
			getchar();
			d=getchar();
			scanf("%lf",&g);
			switch(d)
			{
			case 'a':
				price[0]+=1.5*g;
				weight[0]+=g;
				break;
			case 'o':
				price[1]+=1.4*g;
				weight[1]+=g;
				break;
			case 'b':
				price[2]+=1.48*g;
				weight[2]+=g;
				break;
			case 'p':
				price[3]+=1.08*g;
				weight[3]+=g;
				break;
			}
		}
		for(int j=0;j<4;j++)
		{
			sum1+=price[j];
			sum2+=weight[j];
		}
		printf("       apple  orange banana pineapple sum\n");
		printf("price  %-7.2f%-7.2f%-7.2f%-10.2f%-7.2f\n",price[0],price[1],price[2],price[3],sum1);
		printf("weight %-7.2f%-7.2f%-7.2f%-10.2f%-7.2f\n",weight[0],weight[1],weight[2],weight[3],sum2);
		printf("\n");
	}
	return 0;
}

29、求奇数的乘积

题目描述:给你n个整数,求他们中所有奇数的乘积。

思路:循环类型,如果为奇数则将其相乘

#include<iostream>
using namespace std;
int main()
{
int n,sum,c;
while(cin>>n)
{
sum=1;
for(int i=0;i<n;i++)
{
cin>>c;
if(c%2==1)
{
sum*=c;
}
}
printf("%d\n",sum);
}
return 0;
}

30、求最晚和最早日期

题目描述:输入N个日期,每个以年、月、日的顺序读入,打印输出最晚的日期、最早的日期。

思路:循环类型,根据年月日依次比较大小

#include<stdio.h>
int main(){
  int N,i,Y[20],M[20],D[20],zao,wan,z,w;
  scanf("%d",&N);
  for(i=0;i<N;i++)
	  scanf("%d%d%d",&Y[i],&M[i],&D[i]);
   wan=Y[0];w=0;zao=Y[0];z=0;//wan是最晚日期的年,zao是最早日期的年,w是最晚日期的下标,z是最早日期的下标
for(i=1;i<N;i++)//求最晚日期
{
if(Y[w]<Y[i])//判断年份大小
{
wan=Y[i];
w=i;
}
else if(Y[w]==Y[i])//如果年份相等,则判断月份
{
if(M[w]<M[i])
{
w=i;
}
else if(M[w]==M[i])//如果月份相等,则判断日
{
if(D[w]<D[i])
{
w=i;
}
}
}
}
for(i=1;i<N;i++){//同理求最早日期
	   if(zao>Y[i]){zao=Y[i];z=i;}
	   else if(zao==Y[i]){
		   if(M[z]>M[i]) z=i;
		   else if(M[z]==M[i]){
			   if(D[z]>D[i]) z=i;
			   
		   }
	   }
	 
   }
printf("%d %d %d\n",Y[w],M[w],D[w]);  
	 printf("%d %d %d\n",Y[z],M[z],D[z]); 
return 0;
}

31、素数

题目描述:判断一个数是不是素数

思路:循环类型,写一个函数判断是否为素数:将i从2到n-1循环【或者可以到sqrt(n)停止循环】,如果输入的数能够整除i,说明该数不是素数

#include<iostream>
using namespace std;
int su(int n)
{
	int i;
	for(i=2;i<n;i++)
	{
		if(n%i==0)
		{
			return 0;
		}
	}
	return 1;
}
int main()
{
	int n,i;
	int a[100];
	scanf("%d",&n);
	for(i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
	}
	for(i=0;i<n;i++)
	{
		if(su(a[i])==1)
		{
			printf("yes\n");
		}
		else
		{
			printf("no\n");
		}
	}
}

32、计算e

题目描述:利用公式e=1+ 1/1! + 1/2! + 1/3! + … + 1/n!,编程计算e的近似值,直到最后一项的绝对值小于threshold(该项不包括在结果内),输出e的值并统计累加的项数。

思路:循环类型

#include<iostream>
using namespace std;

int main()
{
int n=0;
 double t,e=0,m=1.0;
cin>>t;
while(m>=t)//最后一项的绝对值小于t则跳出循环
{
  n++; //累加的项数
  e+=m; //e的值
  m*=1.0/n;
}
printf("%.6f %d",e,n);
return 0;
}

33 数字之和

题目描述:输入一个正整数,求这个正整数的各位数字之和

思路:循环类型,从个位开始,依次将各位数字相加

#include<iostream>
using namespace std;
int main()
{
int n,sum;
while(cin>>n)
{
sum=0;
while(n!=0)
{
sum+=(n%10);
n=n/10;
}
cout<<sum<<endl;
}
return 0;
}

34 繁殖问题

题目描述:有一家生化所,一月份引入一对新生的小白鼠。这对小白鼠生长两个月后,在第三、第四、第五个月各繁殖一对新小白鼠,在第六个月停止繁殖,在第七个月则死亡。新生的小白鼠也如此繁殖。问在第N个月时,活的小白鼠有多少对?

思路:使用数组m[]先保存前7个月小白鼠的数量,从第8个月开始到第50个月,每个月的小白鼠数量是两个月前、三个月前和四个月前的小白鼠之和

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int main()
{
 int n,res;
int m[50]={1,1,2,3,5,7,10};
while(cin>>n)
{
  for(int i=7;i<50;i++)
  {
    m[i]=m[i-2]+m[i-3]+m[i-4];
  }
 cout<<m[n-1]<<endl;
}
return 0;
}

35 奇妙的数字

题目描述:有一种自然数,它的各位数字之和能被17整除。这个数的后继数(即这个数加1)的各位数字之和也能被17整除。求所有自然数中,从小到大第n个这样的数。

思路:编写一个函数求各个位的数字之和,再使用数组a保存前20个奇妙的数字。

#include<stdio.h>
//求各个位的数字之和
int chu(long n)
{
int t=0;
while(n)
{
t+=(n%10);
n=n/10;
}
return t;
}


int main()
{
int a[50]; //数组a保存奇妙的数字
int count=1;
int i=8899,n;
while(count<20)
{
if(chu(i)%17==0&& chu(i+1)%17==0)
{
a[count++]=i;

}
++i;
}
while(scanf("%d",&count)!=EOF)
{
printf("%d\n",a[count]);
}
return 0;
}

36 整除的尾数

题目描述:一个整数,只知道前几位为a,不知道末二位,被另一个整数b除尽了(即没有余数),那么该数的末二位该是什么呢?

思路:前面有一题和此题几乎相同,前面的那题是一个循环,这题是两个循环

#include <stdio.h>
#include <math.h>
int main(){
int a,b,j,k,total,count=0;

scanf("%d%d",&a,&b);
for(j=0;j<=9;j++)
{
  for(k=0;k<=9;k++)
    {
       total=a*100+j*10+k;
      if(total%b==0)
        {
           count++; 
						if(count>1){
							printf(" ");
							count--;
						}
						printf("%d%d",j,k);
         }
    }
}
return 0;
}

37 黑色星期五

题目描述:13号又是星期五是一个不寻常的日子吗? 13号在星期五比在其他日少吗?为了回答这个问题,写一个程序来计算在n年里13 日落在星期一,星期二…星期日的次数.这个测试从1900年1月1日到 1900+n-1年12月31日.n是一个非负数且不大于400.

这里有一些你要知道的: 1900年1月1日是星期一. 4,6,11和9月有30天.其他月份除了2月都有31天.闰年2月有29天,平年2月有28天

#include <stdio.h>
int main(){
	int n;
	int month[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
	int count_year[7]={0};//星期六----星期五的次数
	int index=1;//编号星期一 
	int s;
	while(scanf("%d",&n)!=EOF){
		for(int year=1900;year<=1900+n-1;year++){//所有的年份 
			//判断闰年 
			if(year%400==0||(year%4==0&&year%100!=0))
				month[2]=29;
			else month[2]=28;
			//1-12月
			for(int m=1;m<=12;m++)
				{
					s=(index+13)%7;
					count_year[s]++;
					index+=month[m];
				 }
			
		}
			 for(int i=0;i<7;i++){
        	if(i<6)
        	 printf("%d ",count_year[i]);
        	 else printf("%d",count_year[i]);
		}
            printf("\n"); 
	}
	return 0;
} 

38 树

题目描述:明明的问题可以归结为:给你一条马路的长度和若干个车站的位置,请你用程序计算出把树移走后,马路上还剩多少棵树。

思路:用数组标识要移走的树和剩余的树,如果是要移走,将其值加1,否则不变,最后统计数组中值为0的数【在马路长度范围内】


#include <iostream>
using namespace std;
 
int main(){
	int l,m;
	int x,y;
	int count;
	
	while(cin>>l>>m){//输入马路长度和要建的车站数
		int a[10000]={0};//数组a用来标识移走的树和剩余的树
		count=0;//count表示剩余的树
		while(m--){
			cin>>x>>y;
			for(int i=x;i<=y;i++){//标识要移走的树
				a[i]++;
			}
		}
 
		for(int j=0;j<=l;j++){
			if(a[j]==0)//统计剩余的树
				count++;
		}
		cout<<count<<endl;
	}
	return 0;

}

39 约瑟夫环

题目描述:明明的问题可以归结为:给你一个公司的人数N和一个淘汰数X,你的程序模拟上面描述的淘汰方式,输出淘汰人的编号顺序。

#include <stdio.h>
int main(){
	int N,x;
	while(scanf("%d%d",&N,&x)!=EOF){
		int a[100];
		int i,k=1;
		for(i=1;i<=N;i++)
			a[i]=i;
		for(i=N;i>=1;i--){
			k=(k+x-1)%i;//k是要淘汰的人的下标
			if(k==0)
				k=i;//因为编号从1开始,若k==0  那么k==i
			if(i>1)//i表示剩余的人数
				printf("%d ",a[k]);
			else printf("%d",a[k]);
			for(int j=k;j<i;j++)
				a[j]=a[j+1];//向前移位 
		}
		printf("\n");
	}
	return 0;
}
 

40 最大与最小

题目描述:明明爸爸的问题可以归结为:在一个由M个整数构成圆环中,找出N个相邻的数,使其和为最大或最小。

思路:用数组保存从第一个数开始相邻的N个数的值,然后从第二个数开始相邻的N个数的值,直到从第m个数开始相邻的N个数的值,对数组排序,最小值就是第一个,最大值就是最后一个,注意要判断数组下标是否越界

#include <cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int cmp(int a,int b)
{
	return a<b;
}
int main() {
	int m,n,i,j,p[105],ret[105],temp;
	while(scanf("%d%d",&m,&n) != EOF) {
		for(i=0;i<m;i++) {
			scanf("%d",&p[i]);
			//初始化 
			ret[i]=0;
		}
		
		for(i=0;i<m;i++) {//从第一个数开始到第m个数
			for(j=i;j<i+n;j++) {//从第i个数开始计算相邻的n个数之和
				if(j>=m) {//如果大于输入的整数个数,需要对整数取余,重新从开头数字相加
					ret[i] += p[j%m]; 
				}else
					ret[i] += p[j];
			}
		}
		//quickSort(0,m-1,ret);
		sort(ret,ret+m,cmp);//从小到大排序
		printf("Max=%d\nMin=%d\n\n",ret[m-1],ret[0]);
	}
	return 0;
}

41 环

题目描述:明明爸爸的问题可以归结为:将1至9这九个数字,以任意顺序排成一个环,请在某两个数字之间剪开,分别按顺时针和逆时针次序排列成两个九位数,要求剪开后所得到的这两个九位数的差能被396整除,问共有几种剪法?

#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    int n,x,y,flag;
    cin >> n;
    for(int i = 1;i <= n;i++)
    {
        int a[9];//a[]存放录入的环
        flag = 0;
        for(int j = 0;j < 9;j++)//录入环
            cin >> a[j];
        for(int j = 0;j < 9;j++)//共9种剪切方式,依次判断
        {
            int sum1 = 0,sum2 = 0;
            int m = 100000000;//乘以的进制数
            for(int k = 0;k < 9;k++) //九个数字
            {
                x = (j + k) % 9;//x顺时针,y逆时针
                y = (j - k - 1) % 9;
                if(y < 0) y = y + 9;//直接跳到最后位
                sum1 += a[x] * m;
                sum2 += a[y] * m;
                m = m / 10; //分别为9,8,7,6.。。
            }
            if((int)(abs(sum1 - sum2)) % 396 == 0) flag++;//如果相减可以被396整除则++
        }
        cout << flag << endl;
    }
}
 

42 求数列项

题目描述:数列是数学世界中一种非常有趣的数字排列规则,它使一串数字相互之间产生了某种联系,变幻无穷。很多数学家对数列产生了浓厚的兴趣,花了很多时间对其进行研究,明明就是其中的一位。一天,他又专注于一种新的数列排列规则,该排列规则满足以下条件:

  1. 该数列的第一个数为1。

  2. 该数列的第二个数为5。

  3. 该数列的第i (其中i > 2)个数为第i - 1个数的数值加上(i - 3) × 3 + 7。

明明很快就推算出了这个数列的前三项数字:

  1. 第一项为1。

  2. 第二项为5。

  3. 第三项为12。(第三项的数字为第二项的数字加上(3 - 3) × 3 + 7,即第三项的数为:5 + (3 - 3) × 3 + 7 = 12)

但是当明明还想继续把数列往下推算的时候,他发现计算量越来越大,计算难度越来越高,计算速度也越来越慢。于是,明明就求助于你这位程序设计专家,帮他写一个程序,计算出数列的前50项,然后当明明需要知道数列中的哪一项的数字时,你就把那一项的数字告诉明明。 明明的问题可以归结为:跟据一个正整数n,要求你输出题目中所描述的数列的第n项数值。

思路:一个递归直接搞定

#include <stdio.h>
#include <stdlib.h>
int calculate(int n){
if(n==1)
  {
    return 1;
  }
  else
   {
         return calculate(n-1)+(n-3)*3+7;
   }
}
int main()
{
int n;
 while(scanf("%d",&n)!=EOF)
  {
    printf("%d\n",calculate(n));
  }
return 0;
}

43 最高频率

题目描述:明明的爸爸的问题可以归结为:给你一个数字串,里面有n个数字,输出这个数字串中出现次数最多的那个数字;如果有多个数字出现次数一样,则输出其中最小的那个数字。

思路:空间换时间,用数组存储对应数字的数量,初始化数组为0,例如a[0]=4,则让b[a[0]]即b[4]++,一次遍历后统计数组b中的最大值

#include <stdio.h>
int main() {
	int n,i,a[205],b[110],index,max;
	while(scanf("%d",&n) != EOF) {
		for(i=0;i<=109;i++)
			b[i]=0;
		for(i=1;i<=n;i++) {
			scanf("%d",&a[i]);
			b[a[i]]++;  
		}
		index=0,max=0;
		for(i=0;i<110;i++) {
			if(b[i]>max) {
				max = b[i];
				index=i;
			}
		}
		printf("%d\n",index);
	}
	return 0;
}

44 三艘船

题目描述:明明的问题可以归结为:给出三艘船的速度,以及它们到达目的地时是几点钟(并不知道分别是哪一天,只知道三艘船都在100天以内到达了终点),求两地间的距离到底有多少。若有多组解,只输出最小的那组解。

#include <stdio.h>
int main(){
	int a,b,c;
	while(scanf("%d%d%d",&a,&b,&c)!=EOF){//时刻 
		int d,e,f;
		scanf("%d%d%d",&d,&e,&f);//速度 
		int flag=1;
		int dis=a*d;//赋初值 初始距离为a船到达时间*速度
		while(flag){
			if((dis/e)%24==b&&(dis/f)%24==c){//如果都是在同一天到达的话
			break;
			}
			else{//a船时间加一天,更新距离
				a+=24;
			    dis=a*d;
			}
		}
		printf("%d\n",dis);
	}
	return 0;
}

45 回文数

题目描述:有一天,明明在做数学作业的时候,发现了一组很有趣的数字。例如1、11、121、1331等等。他发现这些数字都是左右对称的,即不管你把这些数字从左读到右还是从右读到左,读出来的数字都是一样的。于是明明就把这个发现告诉了他爸爸。明明的爸爸是一名数学专家,他当然对这种类型的数字早有研究,他对明明说:“这些是回文数,它是一种特殊的数字现象,即这些数字的左右两边是对称的。例如:121左右两边对称,1331左右也是对称的。”明明觉得这很有趣,接着问他爸爸还有什么和这类回文数有关的好玩的东西,明明的爸爸于是就教了明明一种方法,这种方法是从任意一个整数出发,经过某种计算,就可以得到一个回文数。 这个方法如下: 例如首先给你一个数19,然后把它的最低位与最高位交换(如果还有更多位,则次低位与次高位交换…),得到它的逆序数91,然后两数相加,即19+91=110,我们得到110,因为110不是回文数,因此我们继续上面的步骤,110+11=121,现在我们就得到了一个回文数121。通过这种方法,我们就可以求得一个与某一个整数有关的回文数。 明明很聪明,很快就掌握了这个方法,但是他也发现了一个问题,就是有时候计算一个回文数,需要重复很多次以上的步骤,这使得明明很烦恼。于是他就求助于你,请你帮他写一个程序,通过程序来完成以上求回文数的过程。

明明的问题可以归结为:给你一个整数,通过上面叙述的求回文数的方法,求出回文数,并输出求解过程。输入数据保证该回文数小于2^31

思路:编写两个函数,一个判断是否为回文数,另一个将数字变为逆序数,写一个死循环,如果最终是一个回文数,则退出循环,否则一直循环直到变成回文数

#include <stdio.h>
#include <stdlib.h>
int hui(int n) //判断是否是回数
{
 int sum=0,flag=0,temp=n;
while(temp)
{
 sum=sum*10+temp%10;
 temp/=10;
}
if(sum==n)
{
 flag=1;
}
return flag;
}

int swap(int n) { //得到数字n的逆序数
	int j,ret=0,temp[6],i=0;
	while(n!=0){
		temp[i++]=n%10;
		n/=10;
	}
	for(j=0;j<i;j++)
		ret=ret*10+temp[j];
	return ret;
}

int main()
{
 int n,num1,num2,flag;
 while(scanf("%d",&n) != EOF) {
		if(n==0){
			return 0;
		}
    while(1)
    {
    num1=swap(n);
     num2=num1+n;
    printf("%d+%d=%d\n",n,num1,num2);
    flag=hui(num2);   
    if(flag==1)
     {
        break;
     }
   else
    {
      n=num2;
    }
    }
}
return 0;
}

46 特殊四位数

题目描述:数学一直是明明很喜欢的一门学科,不但上课认真听讲,而且还自己钻研。有一次,老师在课上讲了一种特殊的四位整数,这种整数有两个特性:

第一,它是某一个自然数的平方;

第二,它的千位数字与十位数字之和等于百位数字与个位数字之积。

然后老师就举了一个例子:1156,1156是34的平方,且1156的千位数字1加上十位数字5等于百位数字1乘以个数数字6,即1+5=1*6。

然后老师告诉同学,这是最小的一个符合以上两个特性的四位整数,接着老师就留下了作业,要让同学们回家后尽量多的找出符合这两个特性的特殊四位数。明明回家后,就开始找了起来,1157、1158、1159、……、3136,直到到了3136(3136=5656,3+3=16),明明才找到了第二个这样的特殊四位数。明明觉得这样找下去不是办法,后面还有好几千个数字要一个一个试下来,这样一定无法在睡觉前完成。于是明明就求助于你,帮他写一个程序,从小到大求出所有的这样的特殊四位数,然后当明明想要第几个这样的特殊四位数时,你就能够很快的告诉他。 如果把上述所有的特殊四位数按从小到大的顺序排列后记为S1,S2,…,Sn,…,即排在第1个位置上的特殊四位数记为S1,排在第2个位置上的特殊四位数记为S2,…,排在第n个位置上的特殊四位数记为Sn,
那么明明的问题可以归结为:假如一个特殊四位数排在第n个位置上,那么这个特殊四位数Sn等于多少呢?

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

int judge(int n)//千位数字与十位数字之和是否等于百位数字与个位数字之积
{
  int b[4],i=0,c=n;
  while(n)
{
   b[i++]=n%10;
   n/=10;
}
 if(b[0]*b[2]==b[1]+b[3])
  {
     return c;
  }
else
return 0;
}


int main()
{
  int n,count,i;
  while(scanf("%d",&n)!=EOF){
   count=0;
   for(i=34;i<100;i++) 
    {
     if(judge(i*i)!=0)//该数是一个自然数的平方,若符合条件,则数量加1
    {
     ++count;
    }
    if(count==n)//第n个输出
     {
       break;
     }
    }
printf("%d\n",i*i);
}
return 0;
}

47 最大值

题目描述:明明的问题可以归结为:有N个数字,从中选择出连续的M(L1≤M≤L2)个数,求出它们之和的最大值。

#include<stdio.h>

int main()
{
     int i,n,l1,l2,max,k,j,sum;
     int a[25];
     while(scanf("%d %d %d",&n,&l1,&l2)!=EOF)
     {
          for(i=0;i<n;i++)
          {
               scanf("%d",&a[i]);
          }
        max=-200;
        for(j=l1;j<=l2;j++)//m的范围在l1---l2之间
          {
             
              for(i=0;i+j-1<n;i++)//i+j-1表示下标不能越界
               {
                  sum=0;
                  for(k=i;k<i+j;k++)
                    {
                       sum+=a[k];
                    }
                    if(sum>max)
                       max=sum;
               }
           }
        printf("%d\n",max);

     }
  return 0;
}

48 数列1

#include<stdio.h>

//给你一个数列,要求从中选出1个或连续若干个数,要求这些数的和能被11整除,问这样的选数方法一共有多少种

//依次选择连续若干数相加,K从0到n-1
int main()
{
	int i,n,a[55],sum,count,j,k,l,s;
	while(scanf("%d",&n)!=EOF)
	{
		sum=0;//判断n个数字相加是否可以除11
		count=0;//判断有多少种
		k=0;//定义连续多少个数相加
		for(i=0;i<n;i++)
		{
			scanf("%d",&a[i]);
			sum+=a[i];
		}
		//先判断如果所有数相加的情况
		//如果所有数字小于11则只有0种
		if(sum<11)
		{
			printf("0\n");
		}
		else if(sum==11)
		{
			printf("1\n");
		}
		else
		{
			if(sum%11==0)
			{
				count++;
			}
			while(1)
			{
				//循环数组
				for(i=0;i<n;i++)
				{
					l=0;
					s=0;//s暂时存储连续k个数相加的结果
					//k从0到n-1,即连续的1,2,3...n-1个数的和

					while(l<=k)
					{
						s+=a[i+l];
						l++;  //表示从节点i开始连续k个数相加的结果
					}
					if(s%11==0)
					{
						count++;
					}
					//数组下标越界【重要】
					if(i+l>n-1)
					{
						break;//退出循环
					}
				}
				k++;//k一直递增
				if(k==n-1)//如果k已经是所有数相加则退出循环
				{
					break;//
				}
			}
			printf("%d\n",count);
		}
	}
	return 0;
}

49 修理牛棚

题目描述:在一个暴风雨的夜晚,农民约翰的牛棚的屋顶、门被吹飞了。 好在许多牛正在度假,所以牛棚(牛棚的总数S:1<= S<=200)没有住满。 剩下的牛一个紧挨着另一个被排成一行安置在有屋顶的牛棚来过夜。 所以有些牛棚里有牛,有些没有。

所有的牛棚有相同的宽度,且宽度设为1。 因为有些门遗失,农民约翰需要架起新的木板作为门。 他的新木材供应者将会供应他任何他想要的长度,但是供应者只能提供有限数目的木板。 农民约翰想将他购买的木板总长度减到最少。

计算拦住所有有牛的牛棚所需木板的最小总长度。

输出所需木板的最小总长度作为的答案。

说明:拦住一个牛棚需要的木板长度为1,拦住相邻的三个牛棚则需要木板长度为3。

比如有牛的牛棚编号为:

3 5 8 10 11

并且只能使用两块木板,

则第一块木板从3到5,长度为3,

第二块木板从8到11,长度为4,

因此,需要木板的总长度为7。

#include<iostream>
#include<algorithm>
using namespace std;
bool cmp(int a,int b){
	if(a>b)
		return 1;
	return 0;
}
int main()
{
    int m,c;//m 木板数 c牛数 
    cin>>m>>c;
    int a[100],b[100];
    for(int i=1;i<=c;i++)
    {
        cin>>a[i];//牛 编号 
    }
    sort(a+1,a+c+1);//牛编号 升序排序 注意下标从1开始
    int sum=a[c]-a[1]+1;//牛棚的总长度
    for(int i=1;i<c;i++)
    {
        b[i]=a[i+1]-a[i]-1;//牛棚之间空隙距离差 (均为正数)   
    }
    sort(b+1,b+c,cmp); // 升序排序 
    for(int i=1;i<=m-1;i++)
    	sum-=b[i];
	cout<<sum<<endl;
    return 0;
}

50 按要求输出序列

题目描述:明明的爸爸的问题可以归结为:给你一个数字串,里面有n个数字,首先对数字串中的数字进行处理,删除重复出现的数字(重复出现的数字只保留一个),然后对数字串从小到大进行排序,最后输出排序后的字符串。

思路:排序+去重

#include<stdio.h> 
#define MAX_SIZE 205

void sort(int nums[], int n);
void removeDupl(int nums[], int n);

int main() {
	int n = 0;
	int i = 0;
	int temp = 0;
	int nums[MAX_SIZE] = {0};
	
	while (scanf("%d", &n) != EOF) {
		temp = 0;
		for (i = 0; i < n; i++)
			scanf("%d", &nums[i]);
			
		sort(nums, n);// 排序	
		removeDupl(nums, n);// 去重 
		for (i = 0; i < n; i++) {
			if (nums[i] != -1) {
				temp++;
				if (temp == 1)
					printf("%d", nums[i]);
				else
					printf(" %d", nums[i]);
			}
		} 	
		printf("\n");
	}
	
	return 0;
} 

// 排序
void sort(int nums[], int n) {
	int i = 0, j = 0;
	int temp = 0;
	
	for (i = n - 1; i > 0; i--) {
		for (j = 0; j < i; j++) {
			if (nums[j] > nums[j + 1]) {
				temp = nums[j];
				nums[j] = nums[j + 1];
				nums[j + 1] = temp; 
			}
		}
	}	
} 


// 去重
void removeDupl(int nums[], int n) {
	int i = 0, j = 0;
	int count = 0;
	
	for (i = 0; i < n - 1; i++) {
		if (nums[i] != nums[i + 1]) {// 将不同的数字记下来即可 
			nums[count++] = nums[i];
		} 
	}
	nums[count] = nums[n - 1];// 最后一个数字 
	for (i = count + 1; i < n; i++) {// 置特殊数字 
		nums[i] = -1;
	} 
} 
//法二:去重
/*
for(i=0;i<n;i++)
   {
      for(j=i+1;j<n;j++)
         {
             if(a[i]==a[j])
                {
                    for(temp=j;temp<n-1;temp++)
                        {
                               a[temp]=a[temp+1];
                                 
                        }
         j--;
                                n--;
                 }
          }
   }
   */

51 部落人乘法

题目描述:明明热爱数学,他的爸爸也有意培养明明对数学的兴趣。

一次,为了拓展明明的知识面,爸爸给明明讲了一个原始部落人计算乘法的方法:

据说原始部落人以小石子作为计算工具,并用减半和加倍两种运算就能求得任何两个整数的乘积。

其规则是:

左边不断除2,写下商,舍去余数;

右边不断加倍,直到左边变成1为止。

取结果的方法是:

如果某行左边是偶数,就划去整个这一行;

如果某行左边是奇数,右边剩下的数相加即可。

例如求13与15的乘积的过程是:

计算过程:

13--------15 :13除以2等于6,舍去余数1,15乘以2等于30;

6---------30 :6除以2等于3,30乘以2等于60;

3---------60 :3除以2等于1,舍去余数1,60乘以2等于120;

1---------120 :左边数字为1,停止计算。

取结果过程:

13--------15 :左边是奇数,取15;

6---------30 :左边是偶数,划去;

3---------60 :取60;

1---------120 :取120;

其结果就是: 13*15=15+60+120=195。

明明对爸爸讲的这个故事相当感兴趣,也自己动手开始模拟上面的过程计算起来。刚开始的时候,明明感觉这样计算很有趣,但是时间一长,明明就觉得这样的计算过程很麻烦。他想让你帮他写一个程序,快速的计算出上述乘法最后相加的式子和结果。

明明的问题可以归结为:给你两个整数,使用上面描述的乘法过程,输出最后的相加的式子。

思路:首先a=1的特殊情况要考虑。然后用两个数组分别存储a/2的值和b*2的值,对两个数组遍历,如果遇到第一个数组元素为奇数时,输出第二个数组对应的偶数,直到遇到第一个数组最后一个数,即1,循环停止。

#include <stdio.h>
//使用数组num1存储左边数,num2存储右边数,如果最后num1为1,输出结果,否则输出数组值,sum存储最终的和
int main() {
	int a,b,num1[20],num2[20],i,j=0,sum;
	while(scanf("%d%d",&a,&b) != EOF) {
		i=0;
		if(a==1) {  //a=1特殊情况要考虑
			printf("%d*%d=%d=%d",a,b,b,b);
		} else if(a%2 != 0) {
			sum=b;
			printf("%d*%d=%d+",a,b,b);
		}
		else {
			sum=0;
			printf("%d*%d=",a,b);
		}
		while(a != 1) {
			a=a/2;
			num1[i]=a;
			b=b*2;
			num2[i]=b;
			i++;
		}
		for(j=0;j<i;j++) {
			if(num1[j] ==1) {
				sum += num2[j];
				printf("%d=%d",num2[j],sum);
			} else if(num1[j] %2 != 0) {
				printf("%d+",num2[j]);
				sum += num2[j];
			}
		}
		printf("\n");
	}
	return 0;
}

52 序列

明明的爸爸经常用做游戏的方法启发明明对数学的兴趣。有一次,明明爸爸准备了许多盒子和球,他要和明明做一个放球的游戏。

游戏如下:要将k个小球依次装入到若干个盒子中去(可以使用的盒子数不限)。

小球装入盒子的规则如下:

1)第一个盒子不能为空。

2)依次装入各个盒子的球数必须严格递增。例如:当k=8时,装入方法有1,2,5或1,3,4。

3)装入的盒子数尽可能多。

4)所有相邻盒子的球数之差的绝对值之和最小。

如上例中:装入法1,2,5,则差的绝对值之和为(2-1)+(5-2)=4。装入法1,3,4,则差的绝对值之和为(3-1)+(4-3)=3。因此应该采用后一种装法。

明明明白了规则以后,就兴致盎然地玩起了游戏。起先明明玩得很有劲,每次都能顺利的找出最佳的装小球的方法。但是随着小球数量的增多,装小球的方法也就变得越来越多,明明就需要花更多的时间才能找到最佳的装球方法,这使得明明有些犯难了。于是明明想到了你,他想请你帮他写一个程序,他把小球的数量告诉你,而你的程序用来计算装小球的方法。

明明的问题可以归结为:告诉你小球的数量k,然后通过程序计算出盒子装小球的最佳方法

思路:先根据给出来的球的数量求出最多能使用多少个盒子,然后在这些盒子中从少到多依次放球,即1 2 3 4 5 6……N,剩下的球再从后往前每个盒子里面放一个



#include<stdio.h>
#define MAX_SIZE 145// 最多需要140个盒子 

int main() {
	int k = 0;//k是球的数量
	int i = 0; 
	int boxAmt = 0;// 所需盒子的最大数量 
	int boxBallAmt[MAX_SIZE] = {0};// 每个盒子装球的数量 
	
	while (scanf("%d", &k) != EOF) {
		boxAmt = 1;
		while ((boxAmt * (1 + boxAmt)) / 2 <= k)// 求出盒子最大数量 ,即1+2+3+....+n的和
			boxAmt++;
			
		boxAmt--;
		for (i = 1; i <= boxAmt; i++) {// 每个盒子装最少的球,保证严格递增、盒子数量最多、绝对值之和最小 
			boxBallAmt[i] = i;
			k -= boxBallAmt[i];
		}
		
		if (k > 0) {// 球没有放完 
			for (i = boxAmt; i >= 1; i--) {// 将剩下的球每个盒子加装1个,保证绝对值之和最小 
				boxBallAmt[i]++;
				k--;
				if (k == 0)//球全部放完则跳出循环
					break; 
			}
		}
		
		printf("%d", boxBallAmt[1]);
		for (i = 2; i <= boxAmt; i++)
			printf(",%d", boxBallAmt[i]);
		printf("\n");
	}
	
	return 0;
}

53 双重回文数

题目描述:如果一个数从左往右读和从右往左读都是一样,那么这个数就叫做回文数。例如,12321就是一个回文数,而77778就不是。当然,回文数的首和尾都应是非零的,因此0220就不是回文数。事实上,有一些数(如21),在十进制时不是回文数,但在其它进制(如二进制时为10101)时就是回文数。 编一个程序,从文件读入两个十进制数 N (1<= N <= 15) S (0 <S <10000) 然后找出前N个满足大于S且在两种或两种以上进制(二进制至十进制)上是回文数的十进制数,输出到文件上。 本问题的解决方案不需要使用大于4字节的整型变量。

思路:是回文数的题目的变形,前面的回文数判断是将十进制数字逆序然后判断和原来的数是否相等,这里先把十进制转换为目标进制存储在数组中,使用类似与双指针方法判断转换后的数是否为回文数

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

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int judge(int n,int r) {
	int temp[20],i=0,transfer;
	//进制转换
	while(n!= 0) {
		temp[i]= n%r;
		i++;
		n=n/r;
	}
	transfer=i;
	for(i=0;i<transfer;i++) {
		if(temp[i]!=temp[transfer-i-1]){//判断是否为回文数
			break;	
		}
	}
	if(i==transfer){
		return 1;
	}	
	else{
		return 0;
	}
}

int main(int argc, char *argv[]) {
	int N,S,i,count=0,flag,k,r;
	scanf("%d%d",&N,&S);
	i=S+1;
	while(count!=N) {//统计前n个回文数
		k=0;//记录二进制至十进制上是回文数的十进制数的个数
		for(r=2;r<=10;r++) {
			flag=judge(i,r);  //进制转换
			if(flag==1){//如果是回文数则加1
				++k;
			}
			if(k>=2) {  //当该数满足在两种或两种以上进制(二进制至十进制)上是回文数的十进制数时,输出该数,并令count++				
			    printf("%d\n",i);
				++count;
				break;
			}
		}
		++i;
	}
	return 0;
}

54 等差数列

题目描述:一个等差数列是一个能表示成a, a+b, a+2b,…, a+nb (n=0,1,2,3,…) 在这个问题中a是一个非负的整数,b是正整数。

写一个程序来找出在双平方数集合S中长度为n的等差数列。双平方数集合是所有能表示成p2+q2的数的集合。

思路:设置一个标记数组,用于标记某个数是否为双平方数。对于每一个a,b,测试它们确定的一个长度为N的等差数列的每一项是否为双平方数,若测试通过,则输出a,b,否则进行下一次测试。


#include<stdio.h>
#include<string.h>
#define MAX_SIZE 250 * 250 * 2

int isDupl[MAX_SIZE];// isDupl[i] = 1表示i为双平方数 

int main() {
	int i = 0, j = 0;
	int N = 0, M = 0;
	int a = 0, b = 0;
	int tag = 0;// 标记是否找到满足条件的数列,默认没有找到 
	int spectrum = 0;// 数的范围 

	scanf("%d%d", &N, &M);
	
	spectrum = M * M * 2; 
	memset(isDupl, -1, sizeof(isDupl));
	for (i = 0; i <= M; i++) {// 先把双平方数集合搞出来 
		for (j = i; j <= M; j++)
			isDupl[i * i + j * j] = 1;
	}
	
	for (b = 1; (N - 1) * b <= spectrum; b++) {// 从b开始,保证先按照b排序,再按a排序 
		for (a = 0; a + ((N - 1) * b) <= spectrum; a++) {
			for (i = 0; i <= N - 1; i++) {// 测试当前a b确定的等差数列的每一项 
				if (isDupl[a + i * b] == -1) {// 某一项不符合条件
					break;
				}
			}	
			if (i > N - 1) {// 数列中的每一项均符合条件
				tag = 1; 
				printf("%d %d\n", a, b); 
			}
		}
	}
	if (!tag) {// 没有找到 
		printf("NONE\n");
	} 
	
	return 0;
}

55 人见人爱A-B

题目描述:A和B是两个集合,A-B求的是两个集合的差,就是做集合的减法运算。(当然,大家都知道集合的定义,就是同一个集合中不会有两个相同的元素,这里还是提醒大家一下)呵呵,很简单吧?

思路:采用暴力解法,先对集合A排序,然后双层循环遍历集合A和B,若A中有元素和B相等,则跳出内层循环,遍历A的下一个元素,若遍历完B后没有元素与A相等,则输出该元素,然后遍历A的下一个元素。

#include <stdio.h>
int main() {
	int T, n,m,i,a[105],b[105],k,j,count,temp;
	scanf("%d",&T);
	for(i=0;i<T;i++) {
		count=0;
		scanf("%d%d",&n,&m);
		for(j=0;j<n;j++)
			scanf("%d",&a[j]);
		for(j=0;j<m;j++)
			scanf("%d",&b[j]);
		//排序
		for(j=0;j<n;j++) {
			for(k=1;k<n-j;k++) {
				if(a[k-1]>a[k]) {
					temp=a[k-1];
					a[k-1]=a[k];
					a[k]=temp;
				}
			}
		}
		//遍历 求出A-B
		for(j=0;j<n;j++) {
			for(k=0;k<m;k++) {
				if(a[j]==b[k])
					break;
			}
			if(k==m) {
				printf("%d ",a[j]);
				count++;
			}
		}
		if(count !=0)
			printf("\n");
		if(count==0)
			printf("NULL\n");
	}
	return 0;
}


56 最少拦截系统

题目描述:某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能达到前一发的高度。

某天,雷达捕捉到敌国的导弹来袭,如果系统数量太少,将导致有可能不能拦截所有的导弹。所以,根据雷达捕捉到的导弹高度,需要预先准备相应数量的拦截系统。

比如导弹的高度依次为:

5 3 4 2 4 1

则一个拦截系统的第一发炮弹必须打到高度5的地方,第二发炮弹打到高度3的地方。

但第三发炮弹打不到高度4的地方(因为每一发炮弹不能达到前一发的高度),所以要使用第二套拦截系统。

第二套拦截系统发射的炮弹高度打到4和2的高度(实际上,要拦截高度为2的炮弹,使用第一套拦截系统或者第二套都可以),

第三套拦截系统发射的炮弹高度打到4和1的高度(实际上,要拦截高度为1的炮弹,三套拦截系统都可以)。

因此,总共需要三套拦截系统。

再比如导弹的高度依次为:

5 3 4 2 3 1

则一个拦截系统的第一发炮弹必须打到高度5的地方,第二发炮弹打到高度3的地方。

但第三发炮弹打不到高度4的地方(因为每一发炮弹不能达到前一发的高度),所以要使用第二套拦截系统。

第二套拦截系统发射的炮弹高度打到4的高度。

再要拦截高度为2的炮弹,使用第一套拦截系统或者第二套都可以,但考虑到后面还需要拦截炮弹,我们这里使用第一套拦截系统(为什么不能用第二套,自己想啦)。

再要拦截高度为3的炮弹,我们使用第二套拦截系统。

再拦截高度为1的炮弹,第一套和第二套系统都可以,我们就使用第二套吧。

因此,总共仅需要两套拦截系统,第一套拦截的是5 3 2,第二套拦截的是4 3 1。

请根据给定的高度数据,帮助计算一下最少需要多少套拦截系统

思路:第一枚导弹的高度即为第一个拦截系统的高度,此后每一枚导弹来的时候,检查一下当前的拦截系统,若有拦截系统的高度大于当前导弹的高度,则更新此拦截系统的高度,若没有,则新增一套导弹拦截系统。


#include<stdio.h>
#include<string.h>
#define MAX_SIZE 1005 

int main() {
	int count = 0;// 拦截系统数量 
	int T = 0, N = 0;
	int i = 0, j = 0;
	int bombHeight[MAX_SIZE] = {0};// 导弹的高度 
	int height[MAX_SIZE] = {0};// 拦截系统的高度 
	
	scanf("%d", &T);
	while (T--) {
		count = 0;// 重置数据 
		memset(height, -1, sizeof(height));
		scanf("%d", &N);
		scanf("%d", &bombHeight[0]);
		
		height[count++] = bombHeight[0];// 第一套拦截系统的高度 
		for (i = 1; i < N; i++) {//注意i从1开始
			scanf("%d", &bombHeight[i]);
			
			for (j = 0; j < count; j++) {//判断是否有拦截系统的高度大于导弹的高度
				if (height[j] > bombHeight[i]) {
					height[j] = bombHeight[i];// 更新拦截系统高度
					break; 
				}
			}
			if (j == count) {//如果没有拦截系统的高度大于导弹高度,则新增一套拦截系统
				height[count++] = bombHeight[i];// 新增一套拦截系统 
			}
		} 
		printf("%d\n", count); 
	}
	
	return 0;
} 

57 求N!

题目描述:给你一个整数N(0 ≤ N ≤ 10000),你的任务是计算并输出 N!

思路:N!会超过int的最大范围,所以要用数组存储N!

#include<iostream>
using namespace std;
int main()
{
    int nums[100000];
    int n;
    nums[0]=1;
    while(scanf("%d",&n)!=EOF){
        int nums[100000];
        nums[0]=1;
        int temp=0;
        int i;//循环变量
        int w=1;//w是位,个位为0
        for(i=2;i<=n;i++)//该for循环对于大于2的阶乘才奏效。
        {
            int num=0;
            for(int j=0;j<w;j++)
            {
                temp=nums[j]*i+num;
                nums[j]=temp%10;
                num=temp/10;
            }
            while(num)
            {
                nums[w]=num%10;
                num/=10;
                w++;
            }
        }
        for(int i =w-1;i>=0;i--){//最终结果要倒序输出
            cout<<nums[i];
        }
        cout<<endl;
    }
    return 0;
}

58 素数表

题目描述:从键盘输入m,n

在屏幕上按每行10个的格式输出m~n之间的全部素数。

请用函数判断一个数是否素数。

思路:用数组存储m~n之间的全部素数,最后全部输出。或者可以不用数组存储,直接输出。本题使用数组存储

#include<iostream>
#include<cmath>
#include<iomanip>
#include<string>
#include<bits/stdc++.h>
using namespace std;
int IsPrime(int x)
{
	if (x == 1)
	{
		return(0);
    }
	for (int i = 2; i < x; i++)
	{
		if (x%i == 0)
		{
			return(0);
		}
	}
	return(1);
};

 
int main()
{
	
	int x, y,j;
	cin >> x >> y;
	int a[100];
	j = 1;
	for (int i = x; i <= y; i++)
	{
		
		if (IsPrime(i) == 1)
		{
			a[j] = i;
			j++;
		}
	}
	for (int k = 1; k <j; k++)
	{
		
		cout << a[k] << " ";
		if (k % 10 == 0)
		{
			cout << endl;
		}
	}

	return 0;
}

59 倒数数列

题目描述:编写程序计算并输出

s=sumk=1n (1/k) = 1+1/2+1/3+…+1/n 的值。

要求定义并调用函数total(n)计算1+1/2+1/3+…+1/n

思路:一个循环搞定

#include<stdio.h>
double  total(int n)
{
int i;
double res;
for(i=1;i<=n;i++)
{
res+=(1.0/i);//注意是1.0,不能用1除,这种经常出现在改错题
}
return res;
}

int main(){
 int n;
 scanf("%d",&n);
 printf("%.3f\n",total(n));
 return 0;

}

60 排列数

题目描述:编写程序计算排列数

Pmn =m! / (m-n)!

要求定义函数fact(n)计算n的阶乘。
main函数中可使用如下形式调用:fact(m)/fact(m-n));

思路:写一个计算阶乘的函数就可以了,本来担心会不会超过int类型的最大范围,结果竟然AC了,Unbelievable。如果不用这种方法,可以看上题的用数组存储阶乘的方法

#include <cstdio>
#include <iostream>
int fact(int f);

int main()
{

    int i, n, m;

    scanf("%d%d", &m, &n);

    printf("%d\n", fact(m) / fact(m - n));

    return 0;
}
int fact(int f)
{
    int fac=1;
    for(int i = 1;i <= f;i++){
        fac*=i;
        
    }
    return fac;
}

61 亲和数

题目描述;古希腊数学家毕达哥拉斯在自然数研究中发现,

220的所有真约数(即不是自身的约数)之和为:

1+2+4+5+10+11+20+22+44+55+110=284。

而284的所有真约数为1、2、4、71、 142,加起来恰好为220。

人们对这样的数感到很惊奇,并称之为亲和数。

一般地讲,如果两个数中任何一个数都是另一个数的真约数之和,则这两个数就是亲和数。

你的任务就编写一个程序,判断给定的两个数是否是亲和数。
请定义一个函数,传入一个数n,返回n的所有真约数之和。

思路:编写一个函数求一个数的所有真约数之和【与求质数步骤类似】,判断a的真约数是否为b,b的真约数是否为a,是的话输出yes,不是则输出no.

#include<stdio.h>

//返回n的所有真约数之和
int sum(int n)
{
	int res=0;
	int i;
	for(i=1;i<n;i++)
	{
		if(n%i==0)
		{
			res+=i;
		}
	}
	return res;
}
int main()
{
	int n,a,b;
	scanf("%d",&n);
	while(n--)
	{
		scanf("%d %d",&a,&b);
		getchar();
		if(sum(a)==b&&sum(b)==a)
		{
			printf("YES\n");
		}
		else
		{
			printf("NO\n");
		}
	}
	return 0;
}

62 分拆素数和

题目描述:把一个偶数拆成两个不同素数的和,有几种拆法呢?

说明:

比如10,可以拆成3+7和5+5以及7+3,

但是3+7与7+3相同,只算一种,5+5由于两个素数相同,不计算在内。

因此,10的拆法只有一种。

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

int isPrime(int n) {//判断素数
	int i;
	if(n==2){
		return 1;
	}
	for(i=2;i<n;i++) {
		if(n%i==0){
			return 0;
		}
	}
	return 1;
}

int main()
{
int t,n,i,j,retCount;
scanf("%d",&t);
for(i=0;i<t;i++)
{ 
    scanf("%d",&n);
    retCount=0; //统计拆法个数
    for(j=2;j<(n/2);j++)
    { 
        if(isPrime(j)==1)
         { 
              if(isPrime(n-j)==1)//判断j和n-j是否都是素数
                 {
                    if(j!=(n-j))//如果不相等,则拆法加一
                     {
                         retCount++;
                     }
                }
         }
    }
printf("%d\n",retCount);
}
return 0;
}

63 歌德巴赫猜想

题目描述:歌德巴赫猜想指出:任何一个大于2的偶数,都可以表示成两个素数的和。例如:8 = 3+5, 44 = 13+31等。试编程在6至100范围内验证歌德巴赫猜想。

思路:怎么这么多判断素数的,做腻了😭

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

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

//判断素数 
int isPrime(int n) {
	int i;
	if(n==2){
		return 1;
	}
	for(i=2;i<n;i++) {
		if(n%i==0){
			return 0;
		}
	}
	return 1;
}

int main(int argc, char *argv[]) {
	int n,temp,i,j,k;
	scanf("%d",&n);
	for(i=0;i<n;i++) {
		scanf("%d",&temp);
		for(j=2;j<temp-2;j++) {
			if(isPrime(j)==1) {
				//直接求temp-j是不是素数 
				if(isPrime(temp-j)==1) {
					printf("%d %d\n",j,temp-j);
					break;
				}
			}
		}
	}
	return 0;
}

64 N的倍数

题目描述:明明的问题可以归结为:任意给定一个自然数N,寻找一个M,要求M是N的倍数,且它的所有各位数字都是由0或1组成,并要求M尽可能小。

思路:题目中规中矩,按照题目要求一步一步做即可

#include<stdio.h>
int fuc(int n,int i)//判断数字是否都是由0和1组成
{
	int num=n;
	while(num>0)
	{
		if(!(num%10==0||num%10==1))
			return 0;
		num=num/10;
	}
	return 1;
}
int main()
{
	int num;
	while(~scanf("%d",&num))
	{
		for(int i=num;i<=1111111111;i++)
		{
			if(fuc(i,num)&&i%num==0)
			{
				printf("%d\n",i);
				break;
			}

		}
	}
	return 0;
}

65 求n天后的日期

题目描述:写一个函数,传入年月日,计算它的第二天,并返回该日期。由用户输入年月日和一个n值,使用前述函数,计算该日期加n天的日期为多少。

思路:需要编写一个函数判断该年该月有多少天,从day开始判断,再从month判断,最后从year判断

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
//返回天数
int count(int year,int month)
{
	int day;
	if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)
	{
		day=31;
	}
	else if(month==4||month==6||month==9||month==11)
	{
		day=30;
	}
	else if(month==2)
	{
		if((year % 4 == 0 && year % 100 != 0 )|| ( year % 400 == 0)){
			day=29;
		}else
		{
			day=28;
		}
	}
	return day;

}
int main()
{
	int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
	int year,month,day,n;
    while(scanf("%d%d%d%d",&year,&month,&day,&n)!=EOF)
	{
		if((year%400==0)||(year&4==0&&year%100!=0))
		{
			months[2]=29;
		}
		day=day+n;
		while(day>months[month])
		{
		//这里年月日都要进行相应计算
			//还要判断是否为闰年,因为年份可能会加
			if((year%400==0)||(year%4==0&&year%100!=0)){
					months[2]=29;//可能接下来还会出现闰年 
				}else{
					months[2]=28;
				}
				day-=months[month];
				month++;
				if(month>12)
				{
					year++;
					month-=12;
				}
		}
		printf("%d %d %d\n",year,month,day);
	}
	return 0;
}

66 菱形输出

明明这次又碰到问题了:

给定一个正整数N,明明的爸爸让他输出一个以Z开始的菱形,以后依次为Y,X…,

比如当N等于1的时候输出图形:

Z

当N等于2的时候,输出图形:(Y前没有空格,Z、X和W前一个空格)

Z

Y X

W

当N等于3的时候,输出图形(Z前两个空格,Y、X前一个空格,W前没有空格…):

Z

Y X

W V

U T

S

明明发现当N很大的时候就不是很容易了,所以找到了你,希望你编写一个程序帮助他

明明的问题可以归结为:输入一个正整数N,输出一个以Z开始的菱形,以后依次为Y,X…。

请尝试定义函数,该函数的功能是输出以上图形的一行。

//方法比较复杂(找规律)
#include <stdio.h>
int main() {
	int N,i,j,m,count;
	while(scanf("%d",&N) != EOF) {
		m=1,count=0; //count:记住字母的个数,便于计算下一个字母 m:用于控制空格的个数
		if(N==1)
			printf("Z\n\n");
		else if(N==2) {
			printf(" Z\n");
			printf("Y X\n");
			printf(" W\n\n");
		} else { 
			//打印上半部分
			for(i=0;i<N;i++) {
				for(j=N-1-i;j>0;j--)
					printf(" ");
				if(i==0)
					printf("Z\n");
				else {
					count++;
					printf("%c",'Z'-count);
					count++;
					for(j=0;j<m;j++)
						printf(" ");
					m += 2;
					printf("%c\n",'Z'-count);
				}
			}
			m -= 4;
			//打印下半部分
			for(i=0;i<N-1;i++) {
				for(j=0;j<=i;j++)
					printf(" ");
				count++;
				printf("%c",'Z'-count);
				count++;
				for(j=0;j<m;j++)
					printf(" ");
				m -= 2;
				if(m != -3)
					printf("%c\n",'Z'-count);
			}
			printf("\n\n");
		}
	}
	return 0;
}

67 三角形的个数

题目描述:根据一个正整数n(3 ≤ n ≤ 100),要求统计出同时满足下列条件的三角形的个数:

边长都是整数。

周长为n。

边长两两不相等。

思路:三层循环暴力破解

#include<stdio.h>
#include<stdlib.h>
int main()
{
  int i,j,k,count,n;
  int temp;
  while(scanf("%d",&n)!=EOF)
  {
       count=0;
       for(i=1;i<=n;i++)
         {
            for(j=i+1;j<=n;j++)
             {
                for(k=j+1;k<=n;k++)
                  {
                      if((i-j)>=0)
                        {
                            temp=i-j;
                         }
                       else
                        {
                             temp=j-i;
                        }
                       if(i+j+k==n&&(i+j)>k&&temp<k)
                         {
                             ++count;
                          }
                  }
              }
         }
printf("%d\n",count);
  }
return 0;
}

68 素数

题目描述:明明想让你帮他写一个程序,用来计算在某一个整数区间内一共有多少个素数。 明明的问题可以归结为:给你一个整数区间,求出在这个区间里共有多少个素数。

不知道哪里出错了?兄弟们帮我看一下,谢谢!

在这里插入图片描述

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

int isPrime(int n){
	int j;
	for(j=2;j<n;j++){
		if(n%j==0){
			return 0;
		}
	}
	return 1;
}

int judge(int m,int n){
	int i,count=0;
	for(i=m;i<=n;i++){
		if(i>1&&isPrime(i)==1){
			++count;
		}
	}
	return count;
} 

int main(int argc, char *argv[]) {
	int m,n,i;
	while(scanf("%d %d",&m,&n)!=EOF){

		printf("%d\n",judge(m,n));
	}
	return 0;
}

69 杨辉三角

在这里插入图片描述

#include<stdio.h> 
int main() 
{ 
    int a[30][30],i,j,n; 
    int T;
scanf("%d",&T);
while(T--)
{
     scanf("%d",&n); 
        for(i=0;i<n;i++) //最左边和最右边的数为1
        { 
            a[i][i]=1; 
                a[i][0]=1; 
        } 
        for(i=2;i<n;i++) //从第三层开始
        { 
            for(j=1;j<i;j++) //从该层的第二个元素开始
            { 
                a[i][j]=a[i-1][j-1]+a[i-1][j]; //等于左上方和上方元素相加
            } 
        }    
            for(i=0;i<n;i++) 
        { 
            for(j=0;j<=i;j++) 
            {       if(j==0) 
                printf("%d",a[i][j]); 
              
            else
                printf(" %d",a[i][j]); 
        }   printf("\n"); 
            } 
printf("\n"); 
}
        return 0 ; 
} 

70 矩阵问题

从键盘上输入一个整数N,按以下规律输出一个(2N+1)*(2N+1)的矩阵:

对角线的值为1,

上半三角区域值为2,

下半三角区域值为3,

左半三角区域的值为4,

右半三角区域的值为5。

#include <stdio.h>
int main()
{
	int n,arr[17][17];
	int i,j,k;
	while(scanf("%d",&n)!=EOF)
	{
		for(i=0;i<2*n+1;i++)
		{
			for(j=0;j<2*n+1;j++)
			{
				if(i==j||i==2*n-j)//对角线和辅对角线值为1hu
					arr[i][j]=1;
				if(i<n)
				{
					if(j>i&&j<2*n-i)//上半
						arr[i][j]=2;
				}
				if(i>n)
				{
					if(j>2*n-i&&j<i)//下半部分
						arr[i][j]=3;
				}
				if(j<n)
				{
					if(i>j&&i<2*n-j)//左半部分
						arr[i][j]=4;
				}
				if(j>n)
				{
					if(i<j&&i>2*n-j)//右半部分
						arr[i][j]=5;
				}

			}
		}
		for(i=0;i<2*n+1;i++)
		{
			for(j=0;j<2*n+1;j++)
			{
				if(j==0)//注意输出的空格
				{
					printf("%d",arr[i][j]);
				}
				else
				{
					printf(" %d",arr[i][j]);
				}
			}
			printf("\n");
		}
	}
}

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值