PTA函数总结
文章目录
PTA统一输入输出(都换行版)
假设是像下面这样统一换行输入然后统一换行输出
这样写前提:要给出需处理数据个数
输入样例:
2
1 1
2 3
输出样例:
1
4
代码范例:
用新数组d存储输入值是否满足,这样可以统一输出
int d[100]={0};
int i;
for(i=0;i<T;i++) {
int n, k;
scanf("%d %d", &n, &k);
d[i]=c(n, k);
}
for(i=0;i<T;i++){
if(d[i]!=0){
printf("%d\n",d[i]);
}
}
PTA输入空格 输出换行
1.输入输出值都存入数组
int A[N],B[N];
for(i=0;i<n;i++) scanf("%d",&A[i]);
...
for(i=0;i<n;i++) printf("%d\n",B[i]);
2. while (scanf(“%d”, &n) == 1)
类似于 7-7 十进制转二进制 这种存入数组后不方便写代码的
while (scanf("%d", &n) == 1) {
......
printf("\n");
}
实验
7-2 验证“哥德巴赫猜想”
数学领域著名的“哥德巴赫猜想”的大致意思是:任何一个大于2的偶数总能表示为两个素数之和。比如:24=5+19,其中5和19都是素数。本实验的任务是设计一个程序,验证20亿以内的偶数都可以分解成两个素数之和。
输入格式:
输入在一行中给出一个(2, 2 000 000 000]范围内的偶数N。
输出格式:
在一行中按照格式“N = p + q”输出N的素数分解,其中p ≤ q均为素数。又因为这样的分解不唯一(例如24还可以分解为7+17),要求必须输出所有解中p最小的解。
输入样例:
24
输出样例:
24 = 5 + 19
思路:
1.先写个素数函数
2.在写个将a分成加法的函数,其中判断加数是否是素数
其中这一段思想很好,就是将a二分然后得到每一对加数
再判断这俩是否都是素数
就不用双重循环一直加到a
那样做运行时间太久了
for (int i = 2; i <= a / 2; i++) {
if (is_prime(i) && is_prime(a - i)) {
printf("%d = %d + %d\n", a, i, a - i);
return; // 直接退出循环
}
}
代码:
#include <stdio.h>
#include <math.h>
int is_prime(int n) {
int i;
if(n==1)
return 0;
for(i=2;i<=sqrt(n);i++){
if(n%i==0)
return 0;
}
return 1;
}
void fenkai(int a) {
if (a % 2 != 0) {
return;
}
int i;
for (i = 2; i <= a / 2; i++) {
if (is_prime(i) && is_prime(a - i)) {
printf("%d = %d + %d\n", a, i, a - i);
return; // 直接退出循环
}
}
}
int main() {
int a;
scanf("%d", &a);
if (a > 2000000000) {
return 0;
}
fenkai(a);
return 0;
}
7-3素数
本题的目标很简单,就是判断一个给定的正整数是否素数。
输入格式:
输入在第一行给出一个正整数N
(≤ 10),随后N
行,每行给出一个小于231的需要判断的正整数。
输出格式:
对每个需要判断的正整数,如果它是素数,则在一行中输出Yes
,否则输出No
。
输入样例:
2
11
111
输出样例:
Yes
No
分析:
for(i=2;i<n;i++)
这道题如果直接用上面的条件完全遍历的话会超时
改为检查到n的开方数就行
for(i=2;i<=sqrt(n);i++)
代码:
#include <stdio.h>
#include <math.h>
int sushu(int n)
{
int i;
if(n==1)
return 0;
for(i=2;i<=sqrt(n);i++){
if(n%i==0)
return 0;
}
return 1;
}
int main()
{
int a,b,c;
scanf("%d",&a);
for(b=0;b<a;b++){
scanf("%d",&c);
if(sushu(c))
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
7-4 出生年
以上是新浪微博中一奇葩贴:“我出生于1988年,直到25岁才遇到4个数字都不相同的年份。”也就是说,直到2013年才达到“4个数字都不相同”的要求。本题请你根据要求,自动填充“我出生于y
年,直到x
岁才遇到n
个数字都不相同的年份”这句话。
输入格式:
输入在一行中给出出生年份y
和目标年份中不同数字的个数n
,其中y
在[1, 3000]之间,n
可以是2、或3、或4。注意不足4位的年份要在前面补零,例如公元1年被认为是0001年,有2个不同的数字0和1。
输出格式:
根据输入,输出x
和能达到要求的年份。数字间以1个空格分隔,行首尾不得有多余空格。年份要按4位输出。注意:所谓“n
个数字都不相同”是指不同的数字正好是n
个。如“2013”被视为满足“4位数字都不同”的条件,但不被视为满足2位或3位数字不同的条件。
输入样例1:
1988 4
输出样例1:
25 2013
输入样例2:
1 2
输出样例2:
0 0001
分析:
1.用数组存放year的各位数值
也能用abcd,方便一点
2.条件判断处需要注意一下
这里分开的if然后比较count和n的大小,代码量会比较小
如果要分开n=1,n=2,n=3,n=4的情况用if,else会比较麻烦,也很容易漏
//比如这里只是判断n=1的情况代码就很多了
if(bir[0] != bir[1] && bir[0] != bir[2] && bir[0] != bir[3]||bir[1] != bir[2] && bir[1] != bir[3]||bir[2] != bir[3]) count=1;
代码:
#include <stdio.h>
int Year(int y,int n){
int bir[4];
int count=1;
bir[0]=y/1000;
bir[1]=y/100%10;
bir[2]=y/10%10;
bir[3]=y%10;
if(bir[0]!=bir[1]&&bir[0]!=bir[2]&&bir[0]!=bir[3])
count++;
if(bir[1]!=bir[2]&&bir[1]!=bir[3])
count++;
if(bir[2]!=bir[3])
count++;
if(count==n) return 1;
else return 0;
}
int main(){
int year,n;
scanf("%d %d",&year,&n);
int i,k=0;
for(i=year;i<3020;i++){
k=Year(i,n);
if(k) break;
}
printf("%d %04d",i-year,i);
return 0;
}
函数2
递归
递归是一种解决问题的方法,其中一个函数通过不断调用自身来解决规模较小的子问题。递归通常涉及两个部分:基本情况和递归关系。
递归的思想过程:
- 基本情况(Base Case): 这是递归函数中最简单、最基础的情况。通常,基本情况是一个问题规模足够小以直接解决的情况,而无需继续递归。
- 递归关系(Recursive Relation): 这是递归函数的核心。在递归关系中,问题被分解成规模较小的子问题,并通过递归调用来解决这些子问题。递归关系必须能够使问题逐渐趋于基本情况。
- 递归调用: 在递归关系中,函数会调用自身,解决规模较小的子问题。这是递归的关键点。
写递归函数技巧
注意:函数中只需要列出两种情况
1.基本情况
2.找关系式表示n
7-9 建国的数学难题
众所周知,建国是一个数学天才,但是今天他被下面这道题考到了,你能帮建国解决这个难题吗?
f(1) = k
f(2) = f(1) + 1
f(3) = f(2) + 1 + 2
…
f(n) = f(n-1) + (1 + 2 + … + n-1)
输入格式:
第一行输出一个整数T,表示样例数。(1 <= T <= 100)
每个样例占一行,输入两个整数n,k。(0 < n, k <= 1000) 。
输出格式:
每个样例输出一个整数表示f(n)。
输入样例:
2
1 1
2 3
输出样例:
1
4
主要代码:
#include <stdio.h>
// 计算 f(n) 的函数
int c(int n, int k) {
if (n == 1) {
return k;
} else {
return c(n - 1, k) + (n - 1) * n / 2;
}
}
7-6 超级楼梯1
Problem Description
有一超级楼梯,共无限级。刚开始时你在地面,你可以一步跨上第一级,也可以一步跨上第二级。
假设你每次只能向上跨一级或二级,那么你要走上第N级,共有多少种走法?
Input
输入数据首先包含一个整数N,表示测试实例的个数,然后是N行数据,每行包含一个整数M(1<=M<=40),表示楼梯的级数。
Output
对于每个测试实例,请输出不同走法的数量
Sample Input
2
5
8
Sample Output
2
8
34
思路:
(涉及到动态规划) 但我还没学到 浅显解释一下
-
设置dp数组存储到达每个台阶可以用的方法
-
当我们到达一个特定的台阶时,我们可以选择两种方式:
(1)从倒数第一个台阶(前一级台阶)跨一步到达当前台阶。
(2)从倒数第二个台阶(前两级台阶)跨两步到达当前台阶。
这意味着到达当前台阶的方法总数就是到达前一级台阶的方法数加上到达前两级台阶的方法数之和。
因此可以得到等式 dp[i] = dp[i-1] + dp[i-2]
代码:
#include <stdio.h>
int countWays(int n) {
int dp[n + 1]; //要算到n个台阶,所以数组存储扩大一个
int i;
dp[0] = 1;
dp[1] = 1;
for (i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
int main() {
int M;
while (scanf("%d", &M)!=EOF) {
printf("%d\n", countWays(M));
}
return 0;
}
7-7 十进制转二进制
编写一个函数,其参数是一个整数N,返回值也是一个整数(假设是R),规则是整数R写出来(输出出来)是N的二进制形式。例如:参数是15,返回值应是1111。主函数中输入若干组整数,依次输出其二进制形式。
输入样例:
15 16 17 63 64 65
输出样例:
1111
10000
10001
111111
1000000
1000001
输入样例:
0 1 123 456 789
输出样例:
0
1
1111011
111001000
1100010101
思路:
递归:假设输入16, 进入函数dectobin(16)
- 第一次递归调用: dectobin(8)。此时,n / 2 的值是8,所以程序进入下一层递归。
- 第二次递归调用: dectobin(4)。同样,n / 2 的值是4,进入下一层递归。
- 第三次递归调用: dectobin(2)。再次,n / 2 的值是2,进入下一层递归。
- 第四次递归调用: dectobin(1)。现在,n / 2 的值是1,继续递归。
- 递归终止条件: 当 n 等于0或1时,不再递归,直接输出相应的数字。在这里,dectobin(1) 会输出 “1”。
- 回溯: 然后程序回溯到上一层递归调用,继续执行未完成的部分。在这里,dectobin(2) 接着输出 2 % 2 的余数,即 “0”。
- 再次回溯: 回到 dectobin(4),继续输出 4 % 2 的余数,也是 “0”。
- 最后一次回溯: 回到 dectobin(8),输出 8 % 2 的余数,同样是 “0”。
- 返回到最初的调用: 回到 dectobin(16),输出 16 % 2 的余数,即 “0”。
- 最终结果: 程序完成,输出的结果为 “10000”
注意递归之后的回溯
代码:
注意这里读取输入就不要存入数组了,得到值不好存
#include <stdio.h>
void dectobin(int n) {
if (n == 0)
printf("0");
else if (n == 1)
printf("1");
else {
dectobin(n / 2);
printf("%d", n % 2);
}
}
int main() {
int n;
while (scanf("%d", &n) == 1) {
dectobin(n);
printf("\n");
}
return 0;
}