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就没什么用了,但第一次一定要归零)