PAT练习笔记——3.1 简单模拟

2019年9月PAT - 练习笔记——3.1

以下页码标注的是阅读器中实际页码,而不是书本身自印的页码。

第3章 入门篇(1)——入门模拟

3.1 简单模拟

注意

  1. 各类型范围

    1. 整型

      1. 有符号:

        2字节 [-215, 215-1] = [-32768, 32767],4字节[-231, 231-1] = [-2147483648, 2147483647]

        8字节 [-263, 263-1] = [-9223372036854775808, 9223372036854775807]

      2. 无符号

        2字节 [0, 216-1] = [0, 65535],4字节[0, 232-1] = [0, 4294967295]

        8字节 [0, 264-1] = [0, 1844674407370955161]

    2. 浮点型

      float:比特数为32,有效数字为6-7,数值范围为 -3.4E+38 和 3.4E+38

      double:比特数为64,有效数字为15-16,数值范围为-1.7E-308~1.7E+308

  2. 当A > 0, B > 0, A + B < 0时为正溢出

  3. 当A < 0, B < 0, A + B ≥ 0时为负溢出

  4. 浮点数判相等:abs(a - b) < 1e-8

目录

  1. B1001 害死人不偿命的(3n+1)猜想
  2. B1011 A+B 和 C
  3. B1016 部分 A+B
  4. B1026 程序运行时间
  5. B1046 划拳
  6. B1008 数组元素循环右移问题
  7. B1012 数字分类
  8. B1018 锤子剪刀布
  9. A1042 Shuffling Machine
  10. A1046 Shortest Distance
  11. A1065 A+B and C(64 bit)
  12. B1010 一元多项式求导
  13. A1002 A+B for Polynomials
  14. A1009 Product of Polynomials

  1. B1001 1001 害死人不偿命的(3n+1)猜想

    卡拉兹(Callatz)猜想:

    对任何一个正整数 n,如果它是偶数,那么把它砍掉一半;如果它是奇数,那么把 (3n+1) 砍掉一半。这样一直反复砍下去,最后一定在某一步得到 n=1。卡拉兹在 1950 年的世界数学家大会上公布了这个猜想,传说当时耶鲁大学师生齐动员,拼命想证明这个貌似很傻很天真的命题,结果闹得学生们无心学业,一心只证 (3n+1),以至于有人说这是一个阴谋,卡拉兹是在蓄意延缓美国数学界教学与科研的进展……

    我们今天的题目不是证明卡拉兹猜想,而是对给定的任一不超过 1000 的正整数 n,简单地数一下,需要多少步(砍几下)才能得到 n=1?

    输入格式:

    每个测试输入包含 1 个测试用例,即给出正整数 n 的值。

    输出格式:

    输出从 n 计算到 1 需要的步数。

    输入样例:
    3
    
    输出样例:
    5
    
    1. 我的

      #include <iostream>
      
      using namespace std;
      
      int main(void)
      {
      	int n = 0;
      	cin >> n;
      	
      	int step = 0;
      	while (n != 1) {
      		if (0 == n%2) {
      			n /= 2;
      		}
      		else {
      			n = 3 * n + 1;
      			n /= 2;
      		}
      		++step;
      	}
      	cout << step;
      	
      	return 0;
       } 
      
    2. 《算法笔记》P13


  2. B1011 A+B和C

    给定区间 [−231,231] 内的 3 个整数 ABC,请判断 A+B 是否大于 C

    输入格式:

    输入第 1 行给出正整数 T (≤10),是测试用例的个数。随后给出 T 组测试用例,每组占一行,顺序给出 ABC。整数间以空格分隔。

    输出格式:

    对每组测试用例,在一行中输出 Case #X: true 如果 A+B>C,否则输出 Case #X: false,其中 X 是测试用例的编号(从 1 开始)。

    输入样例:
    4
    1 2 3
    2 3 4
    2147483647 0 2147483646
    0 -2147483648 -2147483647
    
    输出样例:
    Case #1: false
    Case #2: true
    Case #3: true
    Case #4: false
    
    1. 我的

      #include <iostream>
      
      using namespace std;
      
      int main(void)
      {
      	int t = 0;
      	cin >> t;
      	
      	bool flag = true;
      	long long a = 0, b = 0, c = 0;
      	for (int i = 1; i <= t; ++i) {
      		cin >> a >> b >> c;
      		
      		flag = a + b > c;
      		
      		if (flag)
      			cout << "Case #"<< i << ": true" << endl;
      		else
      			cout << "Case #"<< i << ": false" << endl; 
      	}
      	
      	return 0;
       } 
      
    2. 《算法笔记》P14

      题目给出的范围是[-263, 263],8字节的整型的数据范围是[-263, -263-1]

      直接用long long就行,不用加溢出判断


  1. B1016 部分A+B

    正整数 A 的“DA(为 1 位整数)部分”定义为由 A 中所有 DA组成的新整数 PA。例如:给定 A=3862767,DA=6,则 A的“6 部分”PA是 66,因为 A 中有 2 个 6。

    现给定 A、DA、B、DB,请编写程序计算 PA + PB

    输入格式:

    输入在一行中依次给出 A、DA、B、DB,中间以空格分隔,其中 0<A, B<1010

    输出格式:

    在一行中输出 PA + PB 的值。

    输入样例 1:
    3862767 6 13530293 3
    
    输出样例 1:
    399
    
    输入样例 2:
    3862767 1 13530293 8
    
    输出样例 2:
    0
    
    1. 我的

      #include <iostream>
      
      using namespace std;
      
      int calp(int a, int da)
      {
      	int pa = 0;
      	
      	for (;a;a /= 10) {
      		if (a % 10 == da)
      			pa = pa * 10 + da; 
      	}
      	
      	return pa;
      }
      
      int main(void)
      {
      	int a = 0, da = 0, b = 0, db = 0;
      	cin >> a >> da >> b >> db;
      	
      	cout << calp(a, da) + calp(b, db);
      	
      	return 0;
       } 
      
    2. 《算法笔记》P16

      1010超过了4字节int的表示范围(我忘了这茬了,但我上面这份代码过了官网测试点,昏迷)


  2. B1026 程序运行时间

    要获得一个 C 语言程序的运行时间,常用的方法是调用头文件 time.h,其中提供了 clock() 函数,可以捕捉从程序开始运行到 clock() 被调用时所耗费的时间。这个时间单位是 clock tick,即“时钟打点”。同时还有一个常数 CLK_TCK,给出了机器时钟每秒所走的时钟打点数。于是为了获得一个函数 f 的运行时间,我们只要在调用 f 之前先调用 clock(),获得一个时钟打点数 C1;在 f 执行完成后再调用 clock(),获得另一个时钟打点数 C2;两次获得的时钟打点数之差 (C2-C1) 就是 f 运行所消耗的时钟打点数,再除以常数 CLK_TCK,就得到了以秒为单位的运行时间。

    这里不妨简单假设常数 CLK_TCK 为 100。现给定被测函数前后两次获得的时钟打点数,请你给出被测函数运行的时间。

    输入格式:

    输入在一行中顺序给出 2 个整数 C1 和 C2。注意两次获得的时钟打点数肯定不相同,即 C1 < C2,并且取值在 [0,107]。

    输出格式:

    在一行中输出被测函数运行的时间。运行时间必须按照 hh:mm:ss(即2位的 时:分:秒)格式输出;不足 1 秒的时间四舍五入到秒。

    输入样例:
    123 4577973
    
    输出样例:
    12:42:59
    
    1. 我的

      #include <iostream>
      #include <math.h>
      
      using namespace std;
      
      const int CLK_TCK = 100;
      
      int main(void)
      {
      	int c1 = 0, c2 = 0;
      	cin >> c1 >> c2;
      	
      	int second = round(double(c2 - c1) / CLK_TCK);
      	printf("%02d:%02d:%02d", second / 3600, (second % 3600) / 60, second % 60);
      	
      	return 0;
       } 
      
    2. 《算法笔记》P17

      “涉及浮点数会使写法变得复杂,因此不妨直接通过判断C2-C1的后两位来判断是四舍还是五入”

      不复杂啊,懵


  3. B1046 划拳

    划拳是古老中国酒文化的一个有趣的组成部分。酒桌上两人划拳的方法为:每人口中喊出一个数字,同时用手比划出一个数字。如果谁比划出的数字正好等于两人喊出的数字之和,谁就赢了,输家罚一杯酒。两人同赢或两人同输则继续下一轮,直到唯一的赢家出现。

    下面给出甲、乙两人的划拳记录,请你统计他们最后分别喝了多少杯酒。

    输入格式:

    输入第一行先给出一个正整数 N(≤100),随后 N 行,每行给出一轮划拳的记录,格式为:

    甲喊 甲划 乙喊 乙划
    

    其中是喊出的数字,是划出的数字,均为不超过 100 的正整数(两只手一起划)。

    输出格式:

    在一行中先后输出甲、乙两人喝酒的杯数,其间以一个空格分隔。

    输入样例:
    5
    8 10 9 12
    5 10 5 10
    3 8 5 12
    12 18 1 13
    4 16 12 15
    
    输出样例:
    1 2
    
    1. 我的

      #include <iostream>
      
      using namespace std;
      
      int main(void)
      {
      	int han1 = 0, hua1 = 0, han2 = 0, hua2 = 0;
      	int n = 0;
      	cin >> n;
      	
      	int a = 0, b = 0;
      	while (n--) {
      		cin >> han1 >> hua1 >> han2 >> hua2;
      		int sum = han1 + han2;
      		
      		if (hua1 == sum && hua2 != sum)
      			++b;
      		else if (hua1 != sum && hua2 == sum)
      			++a;
      	}
      	cout << a << " " << b;
      	
      	return 0;
       } 
      
    2. 《算法笔记》P18


  4. B1008 数组元素循环右移问题

    一个数组A中存有N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(≥0)个位置,即将A中的数据由(A0A1⋯AN−1)变换为(AN−M⋯AN−1A0A1⋯AN−M−1)(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?

    输入格式:

    每个输入包含一个测试用例,第1行输入N(1≤N≤100)和M(≥0);第2行输入N个整数,之间用空格分隔。

    输出格式:

    在一行中输出循环右移M位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。

    输入样例:
    6 2
    1 2 3 4 5 6
    
    输出样例:
    5 6 1 2 3 4
    
    1. 我的

      #include <iostream>
      
      using namespace std;
      
      int main(void)
      {
      	int n = 0, m = 0;
      	cin >> n >> m;
      	m %= n;
      	
      	int num[100];
      	for (int i = 0;i < n - m;++i)
      		cin >> num[i];
      		
      	if (n - m < n) {
      		int number = 0;
      		cin >> number;
      		cout << number;
      		for (int i = n - m + 1;i < n;++i) {
      			cin >> number;
      			cout << " " << number;
      		}
      		for (int i = 0;i < n - m;++i)
      			cout << " " << num[i];
      	}
      	else {
      		cout << num[0];
      		for (int i = 1;i < n - m;++i)
      			cout << " " << num[i];
      	}
      	
      	return 0;
       } 
      
    2. 《算法笔记》P19

      1. “首先要注意题目并没有给定M的最大值,因此不能直接认为M<N,而需要在读入N后令M = M%N
      2. “处理最后一个数字之后不输出空格可以使用count变量记录已经输出数的个数”
      3. “……按照题目要求来对原数组进行操作,本书在5.2节给出了做法,且这个做法的移动次数是最少的”

  5. B1012 数字分类

    给定一系列正整数,请按要求对数字进行分类,并输出以下 5 个数字

    • A1 = 能被 5 整除的数字中所有偶数的和;
    • A2 = 将被 5 除后余 1 的数字按给出顺序进行交错求和,即计算 n1−n2+n3−n4⋯;
    • A3 = 被 5 除后余 2 的数字的个数;
    • A4 = 被 5 除后余 3 的数字的平均数,精确到小数点后 1 位;
    • A5 = 被 5 除后余 4 的数字中最大数字。
    输入格式:

    每个输入包含 1 个测试用例。每个测试用例先给出一个不超过 1000 的正整数 N,随后给出 N 个不超过 1000 的待分类的正整数。数字间以空格分隔。

    输出格式:

    对给定的 N 个正整数,按题目要求计算 A1~A5 并在一行中顺序输出。数字间以空格分隔,但行末不得有多余空格。

    若其中某一类数字不存在,则在相应位置输出 N

    输入样例 1:
    13 1 2 3 4 5 6 7 8 9 10 20 16 18
    
    输出样例 1:
    30 11 2 9.7 9
    
    输入样例 2:
    8 1 2 4 5 6 7 9 16
    
    输出样例 2:
    N 11 2 N 9
    
    1. 我的

      #include <iostream>
      #include <iomanip>
      
      using namespace std;
      
      int main(void)
      {
      	int n = 0;
      	cin >> n;
      	
      	int a1 = 0, a2 = 0, a3 = 0, a4 = 0, a5 = 0;
      	bool flag2 = true;
      	int count2 = 0, count4 = 0;
      	for (int i = 0;i < n; ++i) {
      		int num = 0;
      		cin >> num;
      		
      		switch (num % 5) 
      		{
      		case 0:
      			if (0 == num % 2)
      				a1 += num;
      			break;
      		case 1:
      			++count2;
      			a2 += (flag2 ? num : - num);
      			flag2 = !flag2;
      			break;
      		case 2:
      			++a3;
      			break;
      		case 3:
      			++count4;
      			a4 += num;
      			break;
      		case 4:
      			if (num > a5)
      				a5 = num;
      			break;
      		default:
      			cerr << "error" ; 
      			break;
      		}
      		
      	}
      	
      	a1 ? (cout << a1) : (cout << "N"); cout << " ";
      	count2 ? (cout << a2) : (cout << "N"); cout << " ";
      	a3 ? (cout << a3) : (cout << "N"); cout << " ";
      	count4 ? (cout << setiosflags(ios::fixed) << setprecision(1) << (double)a4 / count4) : (cout << "N"); cout << " ";
      	a5 ? (cout << a5) : (cout << "N");
      	
      	return 0;
       } 
      
    2. 《算法笔记》P21

      “数组count[5]用以存放五类数字的个数,初值为0;数组ans[5]用以存放五类数字的输出结果,初值为0”


  6. B1010 锤子剪刀布

    大家应该都会玩“锤子剪刀布”的游戏:两人同时给出手势,胜负规则如图所示:

    FigCJB.jpg

    现给出两人的交锋记录,请统计双方的胜、平、负次数,并且给出双方分别出什么手势的胜算最大。

    输入格式:

    输入第 1 行给出正整数 N(≤105),即双方交锋的次数。随后 N 行,每行给出一次交锋的信息,即甲、乙双方同时给出的的手势。C 代表“锤子”、J 代表“剪刀”、B 代表“布”,第 1 个字母代表甲方,第 2 个代表乙方,中间有 1 个空格。

    输出格式:

    输出第 1、2 行分别给出甲、乙的胜、平、负次数,数字间以 1 个空格分隔。第 3 行给出两个字母,分别代表甲、乙获胜次数最多的手势,中间有 1 个空格。如果解不唯一,则输出按字母序最小的解。

    输入样例:
    10
    C J
    J B
    C B
    B B
    B C
    C C
    C B
    J B
    B C
    J J
    
    输出样例:
    5 3 2
    2 3 5
    B B
    
    1. 我的

      #include <iostream>
      
      using namespace std;
      
      void selectMax(int a[])
      {
      	if (a[2] >= a[0]) {
      		if (a[2] >= a[1])
      			cout << 'B';
      		else
      			cout << 'J';
      	} 
      	else {
      		if (a[0] >= a[1])
      			cout << 'C';
      		else
      			cout << 'J';
      	}
      }
      
      int main(void)
      {
      	int n = 0;
      	cin >> n;
      	
      	
      	int a[3] = {0, 0, 0}, b[3] = {0, 0, 0};
      	int awin[3] = {0, 0, 0}, bwin[3] = {0, 0, 0};
      	for (int i = 0;i < n;++i) {
      		char a1 = 0, b1 = 0;
      		getchar();
      		a1 = getchar();
      		getchar();
      		b1 = getchar();
      		
      		if ((a1 == 'C' && b1 == 'C') || (a1 == 'J' && b1 == 'J') || (a1 == 'B' && b1 == 'B')) {
      			++a[1];
      			++b[1];
      		}
      		else if (a1 == 'C' && b1 == 'J') {
      			++a[0];
      			++b[2];
      			++awin[0];
      		}
      		else if (a1 == 'C' && b1 == 'B') {
      			++a[2];
      			++b[0];
      			++bwin[2];
      		}
      		else if (a1 == 'J' && b1 == 'C') {
      			++a[2];
      			++b[0];
      			++bwin[0];
      		}
      		else if (a1 == 'J' && b1 == 'B') {
      			++a[0];
      			++b[2];
      			++awin[1];
      		}
      		else if (a1 == 'B' && b1 == 'J') {
      			++a[2];
      			++b[0];
      			++bwin[1];
      		}
      		else if (a1 == 'B' && b1 == 'C') {
      			++a[0];
      			++b[2];
      			++awin[2];
      		}
      	}
      	cout << a[0] << " " << a[1] << " " << a[2] << endl;
      	cout << b[0] << " " << b[1] << " " << b[2] << endl;
      	
      	selectMax(awin);
      	cout << ' ';
      	selectMax(bwin);
      	
      	return 0;
       } 
      
    2. 《算法笔记》P23

      1. “步骤1:考虑到最后需要输出字典序最小的解,不妨将三种手势先按字典序排序,即B、C、J。可以发现,这个顺序又恰好是循环相克顺序,即……,因此不妨将B、C、J对应位0、1、2,作为一维数组mp的三个元素:……,同时写一个函数change(char c)来将手势对应到数字“

      2. ”步骤2:对每组读入的甲乙手势c1和c2,先将其通过change函数转换为数字k1和k2,然后判断该局输赢。由于设置的顺序恰好就是循环相克顺序,因此k1胜k2的条件是(k1 + 1)%3 == k2,而k1平k2的条件是k1 == k2,k1输k2的条件是(k2 + 1)%3 == k1

      3. 找出甲乙获胜次数最多的手势,并转变回BCJ

        for (int i = 0; i < 3; i++) {
            if (hand_A[i] > hand_A[id1]) id1 = i;
            if (hand_B[i] > hand_B[id2]) id2 = i;
        }
        printf("%c %c\n", mp[id1], mp[id2]);
        

  7. A1042 Shuffling Maching

    Shuffling is a procedure used to randomize a deck of playing cards. Because standard shuffling techniques are seen as weak, and in order to avoid “inside jobs” where employees collaborate with gamblers by performing inadequate shuffles, many casinos employ automatic shuffling machines. Your task is to simulate a shuffling machine.

    The machine shuffles a deck of 54 cards according to a given random order and repeats for a given number of times. It is assumed that the initial status of a card deck is in the following order:

    S1, S2, ..., S13, 
    H1, H2, ..., H13, 
    C1, C2, ..., C13, 
    D1, D2, ..., D13, 
    J1, J2
    

    where “S” stands for “Spade”, “H” for “Heart”, “C” for “Club”, “D” for “Diamond”, and “J” for “Joker”. A given order is a permutation of distinct integers in [1, 54]. If the number at the i-th position is j, it means to move the card from position i to position j. For example, suppose we only have 5 cards: S3, H5, C1, D13 and J2. Given a shuffling order {4, 2, 5, 3, 1}, the result will be: J2, H5, D13, S3, C1. If we are to repeat the shuffling again, the result will be: C1, H5, S3, J2, D13.

    Input Specification:

    Each input file contains one test case. For each case, the first line contains a positive integer K (≤20) which is the number of repeat times. Then the next line contains the given order. All the numbers in a line are separated by a space.

    Output Specification:

    For each test case, print the shuffling results in one line. All the cards are separated by a space, and there must be no extra space at the end of the line.

    Sample Input:
    2
    36 52 37 38 3 39 40 53 54 41 11 12 13 42 43 44 2 4 23 24 25 26 27 6 7 8 48 49 50 51 9 10 14 15 16 5 17 18 19 1 20 21 22 28 29 30 31 32 33 34 35 45 46 47
    
    Sample Output:
    S7 C11 C10 C12 S1 H7 H8 H9 D8 D9 S11 S12 S13 D10 D11 D12 S3 S4 S6 S10 H1 H2 C13 D2 D3 D4 H6 H3 D13 J1 J2 C1 C2 C3 C4 D1 S5 H5 H11 H12 C6 C7 C8 C9 S2 S8 S9 H10 D5 D6 D7 H4 H13 C5
    
    1. 我的

      #include <iostream>
      
      using namespace std;
      
      int main(void)
      {
      	int k = 0;
      	cin >> k;
      	int origin[55], shuffle[55], order[55];
      	for (int i = 1;i <= 54;++i) {
      		origin[i] = i;
      		cin >> order[i];
      	}
      		
      	for (int i = 0;i < k;++i) {
      		for (int j = 1;j <= 54;++j) 
      			0 == i % 2 ? shuffle[order[j]] = origin[j] : origin[order[j]] = shuffle[j];
      	}
      	
      	for (int i = 1;i <= 54;++i) {
      		int num = 0;
      		0 == k % 2 ? num = origin[i] : num = shuffle[i];
      		
      		if (1 <= num && num <= 13) 
      			cout << "S";
      		else if (14 <= num && num <= 26)
      			cout << "H";
      		else if (27 <= num && num <= 39)
      			cout << "C";
      		else if (40 <= num && num <= 52)
      			cout << "D";
      		else
      			cout << "J";
      		
      		int number = num % 13;
      		number ? (cout << number) : (cout << 13);
      		if (i != 54)
      			cout << " ";
      	}
      	
      	return 0;
       } 
      
    2. 《算法笔记》P25

      "mp[] = {S,H,C,D,J},……,==mp[(x - 1) / 13]==即为这张牌对应的花色(……),

      而==(x - 1) % 13 + 1==即为它所属花色下的编号"


  8. A1046 Shortest Distance

    The task is really simple: given N exits on a highway which forms a simple cycle, you are supposed to tell the shortest distance between any pair of exits.

    Input Specification:

    Each input file contains one test case. For each case, the first line contains an integer N (in [3,105]), followed by N integer distances D1 D2DN, where Di is the distance between the i-th and the (i+1)-st exits, and DN is between the N-th and the 1st exits. All the numbers in a line are separated by a space. The second line gives a positive integer M (≤104), with M lines follow, each contains a pair of exit numbers, provided that the exits are numbered from 1 to N. It is guaranteed that the total round trip distance is no more than 107.

    Output Specification:

    For each test case, print your results in M lines, each contains the shortest distance between the corresponding given pair of exits.

    Sample Input:
    5 1 2 4 14 9
    3
    1 3
    2 5
    4 1
    
    Sample Output:
    3
    10
    7
    
    1. 我的

      #include <iostream>
      
      using namespace std;
      
      int main(void)
      {
      	int n = 0;
      	cin >> n;	
      	int d[100001];
      	d[1] = 0;
      	for (int i = 2;i <= n;++i) {
      		cin >> d[i];
      		d[i] += d[i - 1];
      	}
      	cin >> d[0]; 
      	d[0] += d[n];	// 总长度 
      	
      	int m = 0;
      	cin >> m;
      	for (int i = 0;i < m;++i) {
      		int a = 0, b = 0;
      		cin >> a >> b;
      		if (a > b) swap(a, b);
      		
      		int dist = d[b] - d[a];
      		if (dist > d[0] - dist)
      			dist = d[0] - dist;
      			
      		if (i)	
      			cout << endl;
      		cout << dist;
      	}
      	
      	return 0;
       } 
      

      若每次逐段距离相加,最后一个测试点会超时

    2. 《算法笔记》P28

      “……在极端情况下,每次查询都需要遍历整个数组,即有105次操作,而共有104个查询,所以极端情况下会有109次操作,这在100ms的时限内是不能承受的”


  9. A1065 A+B and C

    Given three integers A, B and C in [−263,263], you are supposed to tell whether A+B>C.

    Input Specification:

    The first line of the input gives the positive number of test cases, T (≤10). Then T test cases follow, each consists of a single line containing three integers A, B and C, separated by single spaces.

    Output Specification:

    For each test case, output in one line Case #X: true if A+B>C, or Case #X: false otherwise, where X is the case number (starting from 1).

    Sample Input:
    3
    1 2 3
    2 3 4
    9223372036854775807 -9223372036854775808 0
    
    Sample Output:
    Case #1: false
    Case #2: true
    Case #3: false
    
    1. 我的

      #include <iostream>
      
      using namespace std;
      
      int main(void)
      {
      	int t = 0;
      	cin >> t;
      	
      	bool flag = true;
      	long long a = 0, b = 0, c = 0;
      	for (int i = 1; i <= t; ++i) {
      		cin >> a >> b >> c;
      		
              long long sum = a + b;
      		if (a > 0 && b > 0 && sum < 0)
      			flag = true;
      		else if (a < 0 && b < 0 && sum >= 0)
      			flag = false;
      		else
      			flag = a + b > c;
      		
      		if (flag)
      			cout << "Case #"<< i << ": true" << endl;
      		else
      			cout << "Case #"<< i << ": false" << endl; 
      	}
      	
      	return 0;
       } 
      
    2. 《算法笔记》P29

      1. “……。由于题目给定的A和B最大均为263 - 1,故A + B最大为264 - 2,因此使用long long存储正溢出后的值的区间为[-263, -2](由(264 - 2) % 264 = -2可得右边界)。所以,当A>0, B>0, A+B<0时为正溢出,输出true”

      2. “……。由于题目给定的A和B最小均为-263,故A + B最小为-264,因此使用long long存储负溢出后的值的区间为[0, 263-1](由(-264) % 264 = 0可得左边界)。所以,当A<0, B<0, A+B>=0时为负溢出,输出false”

      3. “经测试,数据中并没有A或B取到263的情况,因此题目中的数据范围可能是写错了,应该是……,否则就要用带负数的大整数运算了(因为long long存储263时会自动变成-263,无法区分左右边界)”

        1. 记得long long最大是263-1而不是263
      4. “A + B必须存放到long long型变量中才可与C进行比较,而不可在if的条件中直接相加与C比较,否则会造成后两组数据错误”

        1. 亲测:A + B必须存放到long long型变量中,但可以直接相加与C比较,也就是可以

          long long sum = a + b;
          if (a > 0 && b > 0 && a + b < 0)
          	flag = true;
          else if (a < 0 && b < 0 && a + b > 0)
          	flag = false;
          else
          	flag = a + b > c;
          

          以上代码能通过测试,但若去掉第一行,后两组测试点答案错误

          原因不明


  10. B1010 一元多项式求导

    设计函数求一元多项式的导数。(注:xnn为整数)的一阶导数为nxn−1。)

    输入格式:

    以指数递降方式输入多项式非零项系数和指数(绝对值均为不超过 1000 的整数)。数字间以空格分隔。

    输出格式:

    以与输入相同的格式输出导数多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。注意“零多项式”的指数和系数都是 0,但是表示为 0 0

    输入样例:
    3 4 -5 2 6 1 -2 0
    
    输出样例:
    12 3 -10 1 6 0
    
    1. 我的

      #include <iostream>
      
      using namespace std;
      
      int main(void)
      {
      	int cc = 0, ee = 0;
      	int count = 0;
      	while ((cc = getchar()) != '\n') {
      		ungetc(cc, stdin);
      		cin >> cc >> ee;
      		
      		if (ee) {
      			if (count) cout << " ";
      			++count;
      			cout << cc * ee << " " << ee - 1;	
      		}	
      	}
      	if (!count) cout << "0 0"; 
      	
      	return 0;
       }
      
    2. 《算法笔记》P31

      1. 如果求导之后没有任何非零项,需要输出0 0, 这是本题的一个陷阱

      2. 判断文件末尾

        while (scanf("%d %d", &k, &e) != EOF)
        
      3. 题目已经明确说了以指数递降方式输入,所以我觉得参考代码中再对这进行处理多余了


  11. A1002 A + B for Polynomials

    This time, you are supposed to find A + B where A and B are two polynomials.

    Input Specification:

    Each input file contains one test case. Each case occupies 2 lines, and each line contains the information of a polynomial:

    K N1aN1N2aN2 … NKaNK

    where K is the number of nonzero terms in the polynomial, Ni and aNi (i=1,2,⋯,K) are the exponents and coefficients, respectively. It is given that 1≤K≤10,0≤NK<⋯<N2<N1≤1000.

    Output Specification:

    For each test case you should output the sum of A and B in one line, with the same format as the input. Notice that there must be NO extra space at the end of each line. Please be accurate to 1 decimal place.

    Sample Input:
    2 1 2.4 0 3.2
    2 2 1.5 1 0.5
    
    Sample Output:
    3 2 1.5 1 2.9 0 3.2
    
    1. 我的

      #include <iostream>
      #include <iomanip>
      #include <cmath>
      
      using namespace std;
      
      const float EPS = 1E-8;
      
      int main(void)
      {
      	int count = 0;
      	int k = 0;
      	float a[1001] = {0};
      	int ee = 0;
      	float cc = 0;
      	
      	cin >> k;
      	for (int i = 0;i < k;++i) {
      		cin >> ee >> cc;
      		a[ee] = cc;
      		++count;
      	}
      	cin >> k;
      	for (int i = 0;i < k;++i) {
      		cin >> ee >> cc;
      		if (abs(a[ee]) < EPS) ++count;
      		a[ee] += cc;
      		if (abs(a[ee]) < EPS) --count;
      	}
      	cout << count;
      	
      	for (int i = 1000;i >= 0;--i) {
      		if (abs(a[i]) > EPS) cout << " " << i << " " << setiosflags(ios::fixed) << setprecision(1) << a[i];
      	}
      	
      	return 0;
       }
      

      注意 k 只是非零项项数,不是最高阶数

    2. 《算法笔记》P32

      可以存个max_n,缩小最后遍历范围


  12. A1009 Product of Polynomials

    This time, you are supposed to find A x B where A and B are two polynomials.

    Input Specification:

    Each input file contains one test case. Each case occupies 2 lines, and each line contains the information of a polynomial:

    K N1aN1N2aN2 … NKaNK

    where K is the number of nonzero terms in the polynomial, Ni and aNi (i=1,2,⋯,K) are the exponents and coefficients, respectively. It is given that 1≤K≤10,0≤NK<⋯<N2<N1≤1000.

    Output Specification:

    For each test case you should output the product of A and B in one line, with the same format as the input. Notice that there must be NO extra space at the end of each line. Please be accurate up to 1 decimal place.

    Sample Input:
    2 1 2.4 0 3.2
    2 2 1.5 1 0.5
    
    Sample Output:
    3 3 3.6 2 6.0 1 1.6
    
    1. 我的

      #include <iostream>
      #include <iomanip>
      #include <cmath>
      
      using namespace std;
      
      const float EPS = 1E-8;
      
      int main(void)
      {
      	int count = 0;
      	int k = 0;
      	float a[1001] = {0}, c[2001] = {0};
      	int ee = 0;
      	float cc = 0;
      	
      	int max_e = -1, min_e = 1001;
      	cin >> k;
      	for (int i = 0;i < k;++i) {
      		cin >> ee >> cc;
      		a[ee] = cc;
      		
      		if (ee > max_e) max_e = ee;
      		if (ee < min_e) min_e = ee;
      	}
      	
      	int max_ee = -1, min_ee = 2001;
      	cin >> k;
      	for (int i = 0;i < k;++i) {
      		cin >> ee >> cc;
      		
      		for (int j = max_e;j >= min_e;--j) {
      			if (c[j + ee]) --count;
      			c[j + ee] += a[j] * cc;
      			if (abs(c[j + ee]) > EPS) ++count;
      			
      			if (j + ee > max_ee) max_ee = j + ee;
      			if (j + ee < min_ee) min_ee = j + ee;
      		}
      	}
      	cout << count;
      	
      	for (int i = max_ee;i >= min_ee;--i) {
      		if (abs(c[i]) > EPS) cout << " " << i << " " << setiosflags(ios::fixed) << setprecision(1) << c[i];
      	}
      	
      	return 0;
       }
      

      注意c数组范围要比a数组范围大

    2. 《算法笔记》P35

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值