PTA基础编程题目集编程题C、Java实现,记录一下遇到的问题,及时复习浏览一下。也希望帮助到一直没过某个测试点小伙伴。(有的两种语言代码太相似了,就没有用java再写一遍)
文章目录7-1 厘米换算英尺英寸7-2 然后是几点7-3 逆序的三位数7-4 BCD解密7-5 表格输出7-6 混合类型数据格式化输入7-7 12-24小时制7-8 超速判断7-9 用天平找小球7-10 计算工资7-11 分段计算居民水费7-12 两个数的简单计算器7-13 日K蜡烛图7-14 求整数段和7-15 计算圆周率7-16 求符合给定条件的整数集7-17 爬动的蠕虫7-18 二分法求多项式单根7-19 支票面额7-20 打印九九口诀表7-21 求特殊方程的正整数解7--22 龟兔赛跑7-23 币值转换7-24 约分最简分式7-25 念数字7-26 单词长度7-27 冒泡法排序7-28 猴子选大王7-29 删除字符串中的子串7-30 字符串的冒泡排序7-31 字符串循环左移7-32 说反话-加强版7-33 有理数加法7-34 通讯录的录入与显示7-35 有理数均值7-36 复数四则运算7-37 整数分解为若干项之和7-38 数列求和-加强版 总结
7-1 厘米换算英尺英寸
#include#include void Print_FootAndInch ( int N ); int main() { int N; scanf("%d", &N); Print_FootAndInch(N); return 0; } void Print_FootAndInch ( int N ) { int foot = floor(N/30.48); float temp = (N-foot*30.48)*12; float inch = floor(temp/30.48); printf("%d %0.f", foot, inch); }
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int N = in.nextInt(); int foot = (int) Math.floor(N/30.48); float temp = (float) ((N-foot*30.48)*12); int inch = (int) Math.floor(temp/30.48); System.out.println(foot+" "+inch); in.close(); } }7-2 然后是几点
#includevoid Print_Time ( int N, int pass); int main() { int N; int pass; scanf("%d", &N); scanf("%d", &pass); Print_Time(N, pass); return 0; } void Print_Time ( int N, int pass ) { int minute = N%100; int hour = N/100; int h = hour + pass/60; int m = minute + pass%60; if(m>=60) { h += m/60; m %= 60; } while(m < 0) { h--; m += 60; } printf("%01d%02d", h, m); }
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int N = in.nextInt(); int pass = in.nextInt(); int minute = N%100; int hour = N/100; int h = hour + pass/60; int m = minute + pass%60; if(m>=60){ h += m/60; m %= 60; } while(m < 0){ h--; m += 60; } System.out.print(String.format("%01d", h)); System.out.print(String.format("%02d", m)); in.close(); } }7-3 逆序的三位数
#include#include int main() { char* str = (char*)malloc(sizeof(char)*3); scanf("%s",str); if(str[2] == '0') { if(str[1] == '0') { printf("%c", str[0]); }else { printf("%c", str[1]); printf("%c", str[0]); } }else { printf("%c", str[2]); printf("%c", str[1]); printf("%c", str[0]); } return 0; }
public class B73 { public static void main(String[] args) { Scanner in = new Scanner(System.in); String str = in.next(); if(str.charAt(2) == '0') { if(str.charAt(1) == '0') { System.out.print(str.charAt(0)); }else { System.out.print(str.charAt(1)); System.out.print(str.charAt(0)); } }else { System.out.print(str.charAt(2)); System.out.print(str.charAt(1)); System.out.print(str.charAt(0)); } } }7-4 BCD解密
用一个字节来表达两位十进制的数,每四个比特表示一位。一个字节8bit,一个bit表示0或1。BCD数的十六进制是0x12,它表达的就是十进制的12。0x12按照十六进制%x的输出就是12,理解为BCD数的十进制就是去掉十六进制前面那个符号比较合理 (我开始以为无论十六进制或者是十进制都是从1100得到的,但是0x87转化为二进制1000,0111;87转化为二进制0101,0111不对呀)
但是小明没学过BCD,把所有的BCD数都当作二进制数转换成十进制输出了(就是说0x12=16*1+2=18)
现在,你的程序要读入这个错误的十进制数(18),然后输出正确的十进制数(12)。就是把小明的 *** 作逆过去,十进制换为十六进制。
#includeint main() { int a; scanf("%d",&a); printf("%0x",a); return 0; }
System.out.println("二进制输出"+Integer.toBinaryString(b)); System.out.println("八进制输出"+Integer.toOctalString(b)); System.out.println("十六进制输出"+Integer.toHexString(b));7-5 表格输出
#include7-6 混合类型数据格式化输入int main() { printf("------------------------------------n"); printf("Province Area(km2) Pop.(10K)n"); printf("------------------------------------n"); printf("Anhui 139600.00 6461.00n"); printf("Beijing 16410.54 1180.70n"); printf("Chongqing 82400.00 3144.23n"); printf("Shanghai 6340.50 1360.26n"); printf("Zhejiang 101800.00 4894.00n"); printf("------------------------------------n"); return 0; }
scanf的读入格式是严格对应的
两种读取方式还是有点不同
#includeint main() { float num_float1; int num_int; char num_char; float num_float2; scanf("%f %d %c %f",&num_float1, &num_int, &num_char, &num_float2); printf("%c %d %0.2f %0.2f",num_char, num_int, num_float1, num_float2); return 0; }
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); float N1 = in.nextFloat(); int Int = in.nextInt(); String c = in.next(); //读取空格之前的 float N2 = in.nextFloat(); System.out.println(String.format("%s %d %.2f %.2f", c,Int,N1,N2)); } }7-7 12-24小时制
#includeint main() { int hour; int minute; scanf("%d:%d",&hour, &minute); if(hour > 12) { hour -= 12; printf("%d:%d PM", hour, minute); }else if(hour < 12) { printf("%d:%d AM", hour, minute); }else { printf("12:%d PM", minute); } return 0; }
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String N = in.next(); in.close(); Integer hour = Integer.parseInt(N.split(":")[0]); Integer minute = Integer.parseInt(N.split(":")[1]); if(hour > 12) { hour -= 12; System.out.printf("%d:%d PM", hour, minute); }else if(hour < 12) { System.out.printf("%d:%d AM", hour, minute); }else { System.out.printf("12:%d PM", minute); } } }7-8 超速判断
#include7-9 用天平找小球int main() { int speed; scanf("%d",&speed); if(speed > 60) { printf("Speed: %d - Speeding", speed); }else { printf("Speed: %d - OK", speed); } return 0; }
#include7-10 计算工资int main() { int b1, b2, b3; scanf("%d %d %d",&b1, &b2, &b3); if(b1 == b2) { printf("C"); return 0; } if(b1 == b3) { printf("B"); return 0; } printf("A"); return 0; }
#include7-11 分段计算居民水费int main() { int year; float time; scanf("%d %f",&year, &time); if(year >= 5) { if(time > 40) { printf("%0.2f",2000+(time-40)*1.5*50); return 0; } printf("%.2f",time*50); return 0; }else { if(time > 40) { printf("%0.2f",1200+(time-40)*1.5*30); return 0; } printf("%.2f",time*30); return 0; } return 0; }
#include7-12 两个数的简单计算器int main() { float water; scanf("%f",&water); if(water > 15) { printf("%.2f",water*2.5-17.5); return 0; } printf("%.2f",water*4/3); return 0; }
#include7-13 日K蜡烛图int main() { int n1; char c; int n2; scanf("%d %c %d",&n1, &c, &n2); if(c == '+') { printf("%d",n1+n2); }else if(c == '-') { printf("%d",n1-n2); }else if(c == '*') { printf("%d",n1*n2); }else if(c == '/') { printf("%d",n1/n2); }else if(c == '%') { printf("%d",n1%n2); }else { printf("ERROR"); } return 0; }
#include7-14 求整数段和int main() { float open, high, low, close; scanf("%f %f %f %f",&open, &high, &low, &close); if(close < open) { printf("BW-Solid"); }else if(close > open) { printf("R-Hollow"); }else { printf("R-Cross"); } int type = 0; if(low < close && low < open) { type = 1; } if(high > open && high > close) { type += 2; } if(type == 1) { printf(" with Lower Shadow"); }else if(type == 2) { printf(" with Upper Shadow"); }else if(type == 3) { printf(" with Lower Shadow and Upper Shadow"); } return 0; }
#include7-15 计算圆周率int main() { int a,b; scanf("%d %d",&a, &b); int i = 0; int sum = (a+b)*(b-a+1)/2; while(a <= b) { for(i=0; i<5; i++) { printf("%5d", a); a++; if(a > b) { break; } } printf("n"); } printf("Sum = %d", sum); return 0; }
#include7-16 求符合给定条件的整数集int main() { float sum = 0; float value = 1; int i = 1; float threshold; scanf("%f",&threshold); do { sum += value; value = value*i/(i*2+1); i++; }while(value > threshold); sum += value; printf("%.6f", sum*2); return 0; }
#includeint main() { int begin; scanf("%d",&begin); int a[4]; for(int j=0; j<4; j++) { a[j] = begin; ++begin; } int j = 0; int k = 0; int flag = 1; for(int i=0; i<4; i++) { j = 0; while(j < 4) { if(j == i) { j++; } if(j >= 4) { break; } k = 0; while(k < 4) { while(k == j || k == i) { k++; } if(k >= 4) { break; } if(!flag) { printf(" "); } flag = 0; printf("%d", a[i]); printf("%d", a[j]); printf("%d", a[k]); k++; } j++; } if(i != 3) { printf("n"); flag = 1; } } return 0; }
写复杂了,有更简单的
for(i=n;i<=n+3;i++) for(j=n;j<=n+3;j++) for(k=n;k<=n+3;k++) if(i!=j&&j!=k&&i!=k){ count++; if(count%6==0) printf("%d%d%dn",i,j,k); else printf("%d%d%d ",i,j,k); }7-17 爬动的蠕虫
#include7-18 二分法求多项式单根int main() { int n, u, d; scanf("%d %d %d",&n, &u, &d); int sum = 0; int time = 0; while(sum < n) { sum += u; time++; if(sum >= n) { break; } sum -= d; time++; } printf("%d", time); return 0; }
浮点数为0的判断fabs(value) >= 1e-6,否则陷入死循环
#include7-19 支票面额#include float a3, a2, a1, a0; float count(float x) { return a3*pow(x,3)+a2*pow(x,2)+a1*x+a0; } void findZero(float negative, float positive) { float mid = (negative+positive)/2; float value = count(mid); //printf("mid: %.2f ", mid); //printf(" %.2fn", value); //int counts = 0; while(fabs(value) >= 1e-6) { if(value > 0) { positive = mid; mid = (negative + positive)/2; } else { negative = mid; mid = (negative + positive)/2; } value = count(mid); //printf("mid: %.2f ", mid); //printf(" %.2fn", value); //counts++; } printf("%.2f", mid); } int main() { scanf("%f %f %f %f",&a3, &a2, &a1, &a0); float a, b; scanf("%f %f", &a, &b); float value2 = (a+b)/2; float value = count((a+b)/2); float acount = count(a); float bcount = count(b); //printf("%.2f %.2f %.2fn", acount, bcount, value); if(acount == 0) { printf("%.2f", a); } else if(bcount == 0) { printf("%.2f", b); } else if(acount > 0 && value < 0) { findZero(value2, a); } else if(acount < 0 && value > 0) { findZero(a, value2); } else if(bcount > 0 && value < 0) { findZero(value2, b); } else { findZero(b, value2); } return 0; }
#include7-20 打印九九口诀表int main() { int n, f, y; scanf("%d",&n); for(f=0; f<=99; f++) { for(y=0; y<=99; y++) { if(200*y+2*f+n == 100*f+y) { printf("%d.%d", y, f); return 0; } } } printf("No Solution"); return 0; }
#includeint main() { int n; scanf("%d",&n); for(int r=1; r<=n; r++) { for(int l=1; l<=r; l++) { printf("%d*%d=%-4d", l, r, l*r); } printf("n"); } return 0; }
Java也可以这样输出
System.out.printf("%5d:%-5d AM", hour, minute);7-21 求特殊方程的正整数解
#include7–22 龟兔赛跑int main() { int n; scanf("%d",&n); int put = 1; for(int r=1; r<=100; r++) { for(int l=1; l<=100; l++) { if(r*r+l*l == n && r<=l) { printf("%d %dn", r, l); put = 0; break; } } } if(put) { printf("No Solution"); } return 0; }
#include7-23 币值转换int main() { int t; scanf("%d", &t); if(t <= 10) { printf("^_^ %d", 9*t); return 0; } t -= 10; int tl = 30; int rl = 90; while(t > 0) { if(rl > tl && t>30) { tl += 90; t -= 30; } else if(rl > tl && t<=30) { tl += 3*t; t = 0; } else if(rl <= tl && t>=10) { tl += 30; rl += 90; t -= 10; } else if(rl <= tl && t<10) { tl += t*3; rl += t*9; t = 0; } } if(tl > rl) { printf("@_@ %d", tl); } else if(tl < rl) { printf("^_^ %d", rl); } else { printf("-_- %d", tl); } return 0; }
C、Java的除法是截断的
#includevoid OutPut( char *output, int count) { //处于末尾的0都要省略掉,跳过数组前面的a int end = 0; while(output[end] == 'a') { end += 2; } if(end != 0) { //要把最后那个的单位留下 end -= 1; } char before; for(int i=count-2; i>=end; i--) { //0的后面不跟单位;前一个输出是a,后面接连的a也不能输出2,0008; if((output[i+1] == 'a') || (before == 'a' && output[i] == 'a')) { continue; } printf("%c", output[i]); before = output[i]; } } int main() { int t; scanf("%d", &t); if(t == 0) { printf("a"); return 0; } char unit[8] = {'S', 'B', 'Q', 'W', 'S', 'B', 'Q','Y'}; int u = 0; int tmp; char output[18]; int count = 0; while(t > 0) { tmp = t%10; t /= 10; output[count++] = 97+tmp; output[count++] = unit[u++]; //会多一个单位,输出的时候跳过 } //200080W的单位要带上,所以以万为单位分开输出 if(count <= 8) { //没有上万 OutPut(output, count); } else { char behind[count-8]; for(int i=8; i 7-24 约分最简分式 如果用Java则读入一个字符串在转换为数字Integer.parseInt(N.split("/")[0]);
#includeint commomDivisor(int s, int b) { int tmp1, tmp2; if(s 7-25 念数字 这道题想偷懒用个栈,就用的cpp
#include7-26 单词长度#include #include using namespace std; int main () { int t, tmp; stack stk; scanf("%d", &t); if(t < 0) { printf("fu "); t = abs(t); } if(t == 0) { printf("ling"); return 0; } char const *name[10] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"}; int c = 0; while(t > 0) { tmp = t%10; stk.push(tmp); c++; t /= 10; } while(c>1) { //printf(" %s", name[stk.top()]); cout << name[stk.top()]<< " " ; stk.pop(); c--; } cout << name[stk.top()]; return 0; } 因为结尾有空格干扰,不知道最后计数的是单词还是空格,所以少的一个空格由第一个输出的省略掉。(或者换一种计数方式,不是遇到空格清零,而是这个数不是空格而上一个数是空格清零)
#includeint main() { char c = ' '; int sum = 0; int flag = 0;//排除空句子和前面的空格 int first = 1;//第一个不输出空格 while(c != '.') { scanf("%c", &c); if(c != ' ') { flag = 1; } if(c == ' ' && flag) { if(first) { printf("%d", sum); sum = 0; first = 0; } //排除句子中间出现的空格 if(sum != 0 && !first) { printf(" %d", sum); sum = 0; } } else if(c == '.') { //排除结尾的空格 //空句子什么都不输出 if(sum != 0) { if(first) { //一个单词的情况 printf("%d", sum); break; } printf(" %d", sum); } break; } else if(c != ' ') { sum++; } } return 0; } 用Java写过测试点方便点,但是其实不是特别严谨。C语言好像也能这个思路解题strlen(str)返回单个字符串长度C语言字符串分割
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String N = in.nextLine(); //读一行的数据,如果在句号后面还有单词拿这种方法就不行 String str[] = N.split(" |\."); //题目说这里的单词与语言无关,可以包括各种符号,如果句子里有.也会不对 boolean first = true; for (String retval: str){ if(retval.length() != 0) { if(first) { System.out.print(retval.length()); first = false; continue; } System.out.print(" "+retval.length()); } } } }7-27 冒泡法排序import java.util.Arrays; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int N = in.nextInt(); int K = in.nextInt(); int[] arr = new int[N]; for (int i = 0; i < N; i++) { arr[i] = in.nextInt(); } in.close(); int tmp = 0; while (K > 0) { for (int i = 0; i < N - 1; i++) { if (arr[i] > arr[i + 1]) { tmp = arr[i]; arr[i] = arr[i + 1]; arr[i + 1] = tmp; } } K--; } // System.out.println(Arrays.toString(arr)); for (int i = 0; i < N - 1; i++) { System.out.printf("%d ",arr[i]); } System.out.printf("%d",arr[N-1]); } }7-28 猴子选大王#includeint main() { int sum = 0; //报数为3时淘汰猴子,并且sum变为0 int n; scanf("%d", &n); int m = n; //记录还剩多少monkey int p = 0; //数组指针 //int a[n] = {0};不能这样初始化 int a[n]; for(int i=0; i 7-29 删除字符串中的子串 import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String N = in.nextLine(); String mark = in.nextLine(); in.close(); String str[] = N.split(mark); while(str.length != 1) { N = ""; for (String retval: str){ N = N.concat(retval); } str = N.split(mark); } for (String s: str){ System.out.print(s); } } }感觉挨着去比真的麻烦,按照同样的思路,C语言的版本。scanf函数不能接收带空格的字符串,sanf把空格当成结束符。gets()函数从标准输入(键盘)读入一行数据,所谓读取一行,就是遇到换行符就返回。但是不要puts()字符串,会自动带回车,可能被判格式不正确。
#include7-30 字符串的冒泡排序#include int main() { char str[81],mark[81],temp[81]; char *p; gets(str); gets(mark); while((p=strstr(str,mark)) != NULL) { //在字符串str中查找第一次出现字符串mark的位置,不包含终止符 ''。 strcpy(temp, p+strlen(mark)); //把mark所指向的字符串复制到temp, 相当于去覆盖掉了 *p=''; //将str后面的部分都删除掉了 strcat(str, temp); //把tmp所指向的字符串追加到str所指向的字符串的结尾。 } printf("%s", str); return 0; } 比较字符串大小的函数,爱了爱了str.compareTo(str2)
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int N = in.nextInt(); int K = in.nextInt(); String[] arr = new String[N]; for (int i = 0; i < N; i++) { arr[i] = in.next(); } in.close(); String tmp = ""; while (K > 0) { for (int i = 0; i < N - 1; i++) { if (arr[i].compareTo(arr[i + 1]) > 0) { tmp = arr[i]; arr[i] = arr[i + 1]; arr[i + 1] = tmp; } } K--; } for (int i = 0; i < N; i++) { System.out.println(arr[i]); } } }C语言使用stricmp函数编译不通过,使用strcmp才行。
strcmp比较区分字母大小写 相当是比较的时候纯粹按照ascii码值来比较而stricmp是不区分字母的大小写的。而且字符数组的指针不能直接=赋值。如果用gets接收的话,记得在前面加一个getchar。#include7-31 字符串循环左移#include int main() { int N, K; scanf("%d %d", &N, &K); char arr[N][11]; //char *arr[N] for(int i=0; i 0) { for (int i = 0; i < N-1; i++) { if (strcmp(arr[i], arr[i + 1]) > 0) { strcpy(tmp, arr[i]); strcpy(arr[i], arr[i + 1]); strcpy(arr[i + 1], tmp); } } K--; } for (int i = 0; i < N-1; i++) { printf("%sn", arr[i]); } printf("%s", arr[N-1]); return 0; } System.arraycopy(原数组,起始索引,目标数组,目标数组起始下标,要复制的个数);
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String line = in.nextLine(); int N = in.nextInt(); in.close(); char[] c =line.toCharArray(); int L = c.length; char[] c2 = new char[L]; if (N % L == 0) { for (char i : c) { System.out.print(i); } } else { N %= L; System.arraycopy(c, N, c2, 0, c.length - N); System.arraycopy(c, 0, c2, c.length - N, N); for (char i : c2) { System.out.print(i); } } } }#include7-32 说反话-加强版#include int main() { char str[101],temp[101]; char *p; int n; gets(str); scanf("%d", &n); n %= strlen(str); p = str; strcpy(temp, p+n); strncat(temp, str, n); //把 str所指向的字符串追加到 temp所指向的字符串的结尾,直到 n 字符长度为止。 printf("%s", temp); return 0; } 因为用Java实现的过程非常曲折,所以另外写了一篇博客,里面包含java、c、cpp的通过代码,欢迎交流。i’m so vegetables
7-33 有理数加法
#includelong commomDivisor(long s, long b) { long tmp1, tmp2; if(s 7-34 通讯录的录入与显示 这份写的比我好,学习一下,就贴了过来。特别小心一个问题,可能只考虑超出通讯录数量的正数,没考虑负数。
#include#include struct contacts { char name[11]; //字符串结尾有,长度需加1,下同 char birth[11]; char gender; char fphone[17]; //固定电话fixed phone char mphone[17]; //移动电话mobile phone }; void input(); void output(); int main() { int n; scanf("%d", &n); struct contacts t[n]; //定义结构体数组,数组中每个元素都是一个结构体 input(t, n); output(t, n); return 0; } void input(struct contacts p[], int n) { int i; for(i = 0; i < n; i++) { scanf("%s %s %c %s %s", p[i].name, p[i].birth, &p[i].gender, p[i].fphone, p[i].mphone); //gender不是数组,别忘了& } } void output(struct contacts q[], int n) { int m; scanf("%d", &m); int a[m]; //用一个数组记录要查找的记录编号 int j; for(j = 0; j < m; j++) { scanf("%d", &a[j]); } for(j = 0; j < m-1; j++) { if(a[j] >=0 && a[j] < n) { printf("%s %s %s %c %sn", q[a[j]].name, q[a[j]].fphone, q[a[j]].mphone, q[a[j]].gender, q[a[j]].birth); } else { printf("Not Foundn"); } } //最后一次输出 if(a[j] >=0 && a[j] < n) { printf("%s %s %s %c %s", q[a[j]].name, q[a[j]].fphone, q[a[j]].mphone, q[a[j]].gender, q[a[j]].birth); } else { printf("Not Found"); } } 嗐,我发现结尾有回车也没被卡。
import java.util.Scanner; public class Main { public static void main (String [] args) { Scanner in = new Scanner(System.in); int N = in.nextInt();//读入一个整数 in.nextLine(); //想不到竟然这个也有留在缓冲区的,相当关于getchar String[] contact = new String[N];//字符串数组,存每一行信息 for(int i=0; i7-35 有理数均值= N || index < 0) { System.out.println("Not Found"); } else { temp = contact[index].split(" ");// 按照空格拆成字符串,换个顺序输出 System.out.println(temp[0] + " " + temp[3] + " " + temp[4] + " " + temp[2] + " " + temp[1]); } } } } #includelong commomDivisor(long s, long b) { long tmp1, tmp2; if(s 7-36 复数四则运算 %+输出自带的正负号
#include7-37 整数分解为若干项之和#include # define Z 0.04 int main() { float a, b, c, d; scanf("%f %f %f %f", &a, &b, &c, &d); //加法 if(fabs(a+c) <= Z && fabs(b+d) <= Z) { printf("(%.1f%+.1fi) + (%.1f%+.1fi) = 0.0n",a,b,c,d); } else if(fabs(a+c) <= Z) { printf("(%.1f%+.1fi) + (%.1f%+.1fi) = %.1fin",a,b,c,d,b+d); } else if(fabs(b+d) <= Z) { printf("(%.1f%+.1fi) + (%.1f%+.1fi) = %.1fn",a,b,c,d,a+c); } else { printf("(%.1f%+.1fi) + (%.1f%+.1fi) = %.1f%+.1fin",a,b,c,d,a+c,b+d); } //减法 if(fabs(a-c) <= Z && fabs(b-d) <= Z) { printf("(%.1f%+.1fi) - (%.1f%+.1fi) = 0.0n",a,b,c,d); } else if(fabs(a-c) <= Z) { printf("(%.1f%+.1fi) - (%.1f%+.1fi) = %.1fin",a,b,c,d,b-d); } else if(fabs(b-d) <= Z) { printf("(%.1f%+.1fi) - (%.1f%+.1fi) = %.1fn",a,b,c,d,a-c); } else { printf("(%.1f%+.1fi) - (%.1f%+.1fi) = %.1f%+.1fin",a,b,c,d,a-c,b-d); } //乘法 if(fabs(a*c-b*d) <= Z && fabs(b*c+a*d) <= Z) { printf("(%.1f%+.1fi) * (%.1f%+.1fi) = 0.0n",a,b,c,d); } else if(fabs(a*c-b*d) <= Z) { printf("(%.1f%+.1fi) * (%.1f%+.1fi) = %.1fin",a,b,c,d,b*c+a*d); } else if(fabs(b*c+a*d) <= Z) { printf("(%.1f%+.1fi) * (%.1f%+.1fi) = %.1fn",a,b,c,d,a*c-b*d); } else { printf("(%.1f%+.1fi) * (%.1f%+.1fi) = %.1f%+.1fin",a,b,c,d,a*c-b*d,b*c+a*d); } //除法 float x = a*c+b*d; //printf("%fn", x); float y = b*c-a*d; //printf("%fn", y); float bottom = c*c + d*d; //printf("%fn", bottom); if(fabs(x)<=Z && fabs(y)<=Z) { printf("(%.1f%+.1fi) / (%.1f%+.1fi) = 0.0",a,b,c,d); } else if(fabs(x)<=Z) { printf("(%.1f%+.1fi) / (%.1f%+.1fi) = %.1fi",a,b,c,d,y/bottom); } else if(fabs(y)<=Z) { printf("(%.1f%+.1fi) / (%.1f%+.1fi) = %.1f",a,b,c,d,x/bottom); } else { printf("(%.1f%+.1fi) / (%.1f%+.1fi) = %.1f%+.1fi",a,b,c,d,x/bottom,y/bottom); } return 0; } 原作者,感觉真的写的很清楚,转载一波,代码不会写自己去链接里看嚯。
看到这题第一反应是减而治之。很像全排列问题,先写出第一项,再写出剩下的数的分解项。一起来分析步骤。
首先假设我们要求 F ( 4 ) F(4) F(4), 即写出 n = 4 n=4 n=4 的所有分解项。那么我们可以先写出第 1 位的分解项的所有可能。即 k 1 = 1 , 2 , 3 , 4 k_1=1,2,3,4 k1=1,2,3,4。对于每个 k 1 k_1 k1,我们只需求解它的子问题 F ( n − k 1 ) F(n-k_1) F(n−k1) 。
例如:对于 F = 4 F=4 F=4 的情况,第一位 k i k_i ki 所有可能的值为 k i = 1 , 2 , 3 , 4 k_i=1,2,3,4 ki=1,2,3,4 。对于 k i = 1 k_i=1 ki=1,问题被分解成了 F ( 4 ) = 1 + F ( 3 ) F(4)= 1 + F(3) F(4)=1+F(3) 。递归这个过程,得到一棵如下的树:
由于题目中要求结果序列升序排列,所以我们要去除重复情况,分析后发现:对于重复情况,结果序列会出现一个降序的子序列。即为了不重复,我们要保证 k i − 1 < = k i k_{i-1}<=k_i ki−1<=ki 。
整理一下,可得:处于区间 [ 0 , k i − 1 − 1 ] ⋃ ( ⌊ n 2 ⌋ , n ) [0,k_{i-1}-1]bigcup(lfloorfrac n2rfloor,n) [0,ki−1−1]⋃(⌊2n⌋,n) 的情况必须舍去,我们只需要区间 [ k i − 1 , ⌊ n 2 ⌋ ] ⋃ { n } [k_{i-1},lfloorfrac n2rfloor]bigcup{n} [ki−1,⌊2n⌋]⋃{n} 便可。
对于 F = 4 F=4 F=4 ,我们可以看做是 F ( 5 ) = 1 + F ( 4 ) F(5)=1+F(4) F(5)=1+F(4) ,可得 k i − 1 = 1 k_{i-1}=1 ki−1=1,带入刚才推导出的公式得第 1 1 1 位的分解项的所有值为 i = 1 , 2 , 4 i=1,2,4 i=1,2,4。对于 i = 1 i=1 i=1 这种情况,问题被分解成了 1 + F ( n − 1 ) = = 1 + F ( 3 ) 1 + F(n-1) == 1 + F(3) 1+F(n−1)==1+F(3) 。递归得:
递归公式也不难写出来:
F ( n ) = k i + F ( n − k i ) , ( n > 0 ) F(n)=k_i+F(n-k_i), (n>0) F(n)=ki+F(n−ki), (n>0)
相信看到这里很多同学已经能用DFS解出来了,估计核心代码在3、4行左右。但是看到几十层的递归栈······打扰了。我决定再推一下递推式,毕竟性能快好多不是。下面根据递归式去推导递推。
显然,F(n)的分解式不会超过 n n n 项,也就是第一次DFS到底时, 1 + 1 + 1 + ⋅ ⋅ ⋅ + 1 ⏟ n 个 1 underbrace{1+1+1+···+1}_{n个1} n个1 1+1+1+⋅⋅⋅+1这种情况,设为序列 U U U。我们从这种情况开始反推。由于公式为 F ( n ) = k i + F ( n − k i ) F(n)=k_i+F(n-k_i) F(n)=ki+F(n−ki), 将序列 U U U 末尾2位代入公式,得 :
{ k n − 1 = 1 n − k n − 1 = = n − 1 = = 1 ⇒ n = 2 begin{cases} k_{n-1}=1\ n-k_{n-1}==n-1==1Rightarrow n=2end{cases} {kn−1=1n−kn−1==n−1==1⇒n=2此时再判定有无处于区间 [ k n − 1 , ⌊ n 2 ⌋ ] ⋃ { n } [k_{n-1},lfloorfrac n2rfloor]bigcup{n} [kn−1,⌊2n⌋]⋃{n} 的其他 k n − 1 k_{n-1} kn−1,有的话每次只需要处理比当前 k n − 1 k_{n-1} kn−1 大 1 的情况,即如果 j = ⌊ n 2 ⌋ − k n − 1 > 0 j=lfloorfrac n2rfloor-k_{n-1}>0 j=⌊2n⌋−kn−1>0,进行j次循环分解,每次执行 n − = k i + 1 n-=k_i+1 n−=ki+1 ,遇到逆序情况则退出循环,最后存留的 n n n 即为最后一位的值。与递归相反,整个递推过程当 n = 30 n=30 n=30 时自然结束递推了。
7-38 数列求和-加强版一列一列的加,只存一列的和就已经砍掉很多了。
#include#include #include using namespace std; int main () { int A, N; scanf("%d", &A); scanf("%d", &N); if(N == 0){ printf("0"); return 0; } stack stk; long unit; long tmp = 0; while(N > 0) { unit = A*N + tmp; stk.push(unit%10); tmp = unit/10; N--; } if(tmp != 0) { cout << tmp; } while(!stk.empty()) { cout << stk.top(); stk.pop(); } return 0; }
总结Java解题的话,还是有必要学习一下快读快写模板。注意每道题的边界值。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)