PTA实验六答案+笔记

PTA实验六答案+笔记

7-1 判断素数

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

int is_prime(int num) 
{
    if (num <= 1) return 0;
    if (num == 2) return 1;
    if (num % 2 == 0) return 0;
    for (int i = 3; i <= sqrt(num); i += 2) //开方计算就快很多,并且去除偶数影响
        if (num % i == 0) return 0;
    return 1;
}

int main() 
{
    int N;
    scanf("%d", &N);
    for (int i = 0; i < N; i++) 
    {
        int num;
        scanf("%d", &num);
        if (is_prime(num)) 
            printf("Yes\n");
        else 
            printf("No\n");
    }
 return 0;
}

7-2 函数-斐波那契数列

1.采用for循环进行计算,优点是运行快

#include<stdio.h>
double fib(int n) //题目数据过大必须开long int/double类型
{
    long long fib_arr[n+1];
    fib_arr[0] = 0;
    fib_arr[1] = 1;

    for(int i = 2; i <= n; i++) 
        fib_arr[i] = fib_arr[i-1] + fib_arr[i-2];//这里采用for循环

    return fib_arr[n];
}

int main() 
{
    int n;
    scanf("%d", &n);
    printf("%.0lf",fib(n));
    return 0;
}

2.采用递归方式来写,优点是代码相对简单,但运行速度很慢

double fib(int n)
{
    if(n==1||n==2)
        return 1;
    else 
        return fib(n-1)+fib(n-2);//递归
}

3.滚动数组,介于两者之间

double fib(int n)
{
    if(n<2)  return n;
	int dp[2]={0,1};
	int result=0;
	for(int i=2;i<=n;++i)
    {
		result=dp[0]+dp[1];
		dp[0]=dp[1];
		dp[1]=result;
	}
	return dp[1]; 
}

7-3 求阶乘问题

1.正常来算就是直接上for循环然后一项一项加,好处是算的快并且易理解。

#include<stdio.h>
long int jc(long int n)
{
	long int temp=1,i;
	for(i=n;i>=1;i--)
	{
		temp=temp*i;
	}
	return temp;
}
int main() 
{
	long int n=0;
	scanf("%ld",&n);
	printf("%ld",jc(n));
    return 0;
}

2.上递归!!!!!

double jc(int n)
{
	if(n==0)
		return 1;
	else
		return jc(n-1)*n;
}

7-4 递归实现逆序输出整数

#include <stdio.h>
void reverse(int n) 
{
    // 打印出最后一位,包括0,如果是用while循环每次都去*/10那么会忽略掉0
    printf("%d", n % 10);
    if(n >= 10) 
    {
        reverse(n / 10);
    }
}
int main() 
{
    int n;
    scanf("%d", &n);
    reverse(n);
    return 0;
}

7-5 汉诺塔问题

1.算法:原理解释

#include<stdio.h>

void move(char A, char C, int n)
{
	printf("%d: %c -> %c\n", n, A, C);
}

void HanoiTower(char A, char B, char C, int n)
{
	if (n == 1)
	{
		move(A, C, n);
	}
	else
	{
		HanoiTower(A, C, B, n - 1);
		move(A, C, n);
		HanoiTower(B, A, C, n - 1);
	}
}

int main()
{
	int n = 0;
    char a,b,c;
	scanf("%d", &n);
    scanf(" %c %c %c", &a, &c, &b);//a为初始柱,c为目标柱,b为过渡柱
	HanoiTower(a, b, c, n);
	return 0;
}

7-6 打印月历

算法一:安全可靠容易理解

#include<stdio.h>

int is_leap(int year)
{
    return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
}

void print_month(int start_day, int days_in_month)
{
    printf("Sun Mon Tue Wed Thu Fri Sat\n");
    for (int i = 0; i < start_day; i++)
    {
        printf("    ");
    }
    for (int i = 1; i <= days_in_month; i++)
    {
        printf("%3d", i);
        start_day++;
        if (start_day % 7 == 0)
        {
            printf("\n");
        }
        else if(i<days_in_month)//月末的空格不输出
        {
            printf(" ");
        }
    }
}

int main()
{
    int month_days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    int year, month, days_passed = 0;
    scanf("%d %d", &year, &month);

    if (is_leap(year))
    {
        month_days[1] = 29;
    }

    for (int i = 1900; i < year; i++)
    {
        days_passed += is_leap(i) ? 366 : 365;//统计那些过去的日子,三目运算符(判断条件)?(结果为真返回数值):(结果为假返回数值);比if判断简单快捷
    }

    for (int i = 0; i < month - 1; i++)
    {
        days_passed += month_days[i];//加上目标当前年份的天数
    }

    int start_day = (days_passed + 1) % 7;//加一是因为从当月的第一天开始计算
    print_month(start_day, month_days[month - 1]);

    return 0;
}

方法二:

#include<stdio.h>
int ps(int x,int y)
{
	if(y==2)
		if((x%4==0&&x%100!=0)||(x%400==0))
			return 29;
		else
			return 28;
	else if(y==1||y==3||y==5||y==7||y==8||y==10||y==12)
		return 31;
	else
		return 30;
}//判断每月的天数
int main()
{
	int m,y;
	scanf("%d%d",&y,&m);
	printf("Sun Mon Tue Wed Thu Fri Sat\n");//打印月历的开头
	int k=1;
	for(int i=1900;i<y;i++)
		if((i%4==0&&i%100!=0)||(i%400==0))
			k+=366;
		else
			k+=365;
	for(int j=1;j<m;j++)
		k+=ps(y,j);
	k=k%7;//计算第y年m月1号是周几
	//printf("%d",k);//本来出了点问题,用这个来看看
	int t=0,p=0;//两个临时变量
	for(int i=1;i<=ps(y,m);i++)//循环到当月的最后一天
	{
		if(p==0)//用p来看是否已经打印过第一排才打印的空格
		{
			for(int j=0;j<k*4;j++)
				printf(" ");//打印空格
			p=1;
		}
		printf("%3d ",i);//控制格式并打印
		t++;
		if(t+k==7)//如果一排打印完了
		{
			printf("\n");//打印换行
			t=0;
			k=0;//一定要清零
		}
	}
	return 0;
}
/*首先来处理每月的一号是周几:
它告诉我们1900年1月1日为周一,且数据不在1900年之前,所以就可以计算从1900年1月到输入的y年m月共有多少天,储存在k变量中,最后k%7就是星期几了。
怎么计算?循环从1900年到y-1年,每次循环加上第i年的天数(无非就是366和365),最后加上一个循环从y年1月到m月,每次加上那个月的天数就行了。

接下来要处理打印的问题了:
第一:k是0-6,但是月历是从周天,周一,周二……到周六,所以0就代表周天,其他的就是一一对应了。
然后就只有第一排要打印空格,空格数量就是k*4,接着要判断一行是否打完,用一个变量t,每打印一个t++,如果t+k==7,就代表一行打完,变打印一个换行,注意:每打一行t和k都要清零(其实后面k就没什么用了,但第一次一定要归零)
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值