• 蓝桥杯训练4


    复数乘法

    复数可以写成 (A+Bi) 的常规形式,其中 A 是实部,B 是虚部,i 是虚数单位,满足 i​2=−1;也可以写成极坐标下的指数形式 (R×e​(Pi)),其中 R 是复数模,P 是辐角,i 是虚数单位,其等价于三角形式 R(cos§+isin§)。

    现给定两个复数的 R 和 P,要求输出两数乘积的常规形式。

    输入格式:
    输入在一行中依次给出两个复数的 R1, P​1,R​2,P​2,数字间以空格分隔。

    输出格式:
    在一行中按照 A+Bi 的格式输出两数乘积的常规形式,实部和虚部均保留 2 位小数。注意:如果 B 是负数,则应该写成 A-|B|i 的形式。

    输入样例:

    2.3 3.5 5.2 0.4
    

    输出样例:

    -8.68-8.23i
    

    解题思路:
    Alice:看起来挺简单的。
    Bob: 看通过率就知道这题有坑。
    Alice: 哪有坑啊?
    Bob: 没看出来,先试试吧。
    Alice: 有坑,后两个测试点过不去。
    Bob: 看下别人怎么做的?
    Alice: 你就不能自己想出来吗?
    Bob: 想出来,我不想出来。╭(╯^╰)╮
    Alice: 我知道了,截断?浮点数的误差?-0.00?
    Bob: (^U^)ノ~YO不错不错,应该是最后一个。保留两位小数其实是去掉了两位小数位后面的位,也就是截断。这样就可能出现问题,比如说-0.001截断之后变成了-0.00,这时候应该把符号去掉的。
    Alice: 还有这样的题目啊》》
    Bob:看起来不像是光明正大的考察,其实是难度增加了。明天要是晴天就好了~

    顺便复习一下复数的运算法则

    • a+bi 和 c+di
    • 加法:(a+c) + (b+d)i
    • 减法:(a-c) + (b-d)i
    • 乘法:(ac-bd) + (bc+ad)i
    • 除法:(ac+bd)/(cc+dd) + (bc+ad)/(cc+dd)i

    易错点:

    • 保留两位小数,意味着“截断”,截断就有可能出现 - 0.00的情况。如 "{:.2f}+{:.2f}i".format(-0.001, 1251314)"

    大C的AC

    #include <stdio.h>
    int main(){
        double r1,p1,r2,p2;      
        double a, b;
        scanf("%lf %lf %lf %lf", &r1, &p1, &r2, &p2);
        a = r1 * r2 * cos(p1 + p2);    
        b = r1 * r2 * sin(p1 + p2);
        if(a < 0 && a > -0.005) a = 0;  
        if(b < 0 && b > -0.005) b = 0;
        printf("%.2lf%+.2lfi", a, b);
        return 0;
    }
    

    Java的AC

    import java.util.Scanner;
     
    public class Main {
    	public static void main(String[] args) {
    		Scanner sc = new Scanner(System.in);
    		double r1 = sc.nextDouble();
    		double p1 = sc.nextDouble();
    		double r2 = sc.nextDouble();
    		double p2 = sc.nextDouble();
    		double a = r1 * r2 * Math.cos(p1+p2);
    		double b = r1 * r2 * Math.sin(p1+p2);
    		if (a < 0 && a > -0.005) {
    			a = 0;
    		}
    		if (b < 0 && b > -0.005) {
    			b = 0;
    		}
    		System.out.printf("%.2f%+.2fi
    ", a, b);//%+.2f是输出保留两位小数的浮点数,且必须输出符号
    	}
    }
    

    python的AC

    import math
    # 需要使用math计算三角函数
    def main():
        
        R1, P1, R2, P2 = (float(x) for x in input().split())
        # 接收输入的两个复试,其中R 和 P分别是复数模和幅角
        # 我们使用复数的指数形式来计算两个复数的乘法。即(R1 * exp​(P1)​​ ) * (R2 * exp​(P2)​​ ) == (R1 * R2 * exp​(P1 + P2)​​ )
        A, B = to_ab(R1 * R2, P1 + P2)
        # 然后我们把复数的指数形式转换成普通形式,其中A = R * cos(P) , B = R * sin(P)。即通过复数的三角形式完成转换。
        if abs(A) < 0.01:
            # 由于结果要求保留两位小数,两位小数后面的位将被截断。
            # 如 - 0.001将变成-0.00,这是不满足要求的,所以这里直接置零比较好。
            A = 0
        if abs(B) < 0.01:
            # 同上
            B = 0
            
        if B < 0:
            # 按照要求,保留两位小数,如果 B<0 输出A-|B|i
            answer = "{:.2f}-{:.2f}i".format(A, abs(B))
        else:
            answer = "{:.2f}+{:.2f}i".format(A, B)
        print(answer)
    
    
    def to_ab(R, P):
        """通过复数的三角形式将复数从指数形式变成普通形式。输入是指数形式中的 复数模
        和 幅角,输出为 复数的实部和虚部。"""	
        return R * math.cos(P), R * math.sin(P)
    
    if __name__ == '__main__':
        main()
    

    别人家的AC

    import math
    a = [float(i) for i in input().split()]
    x1 = a[0]*math.cos(a[1])
    x2 = a[0]*math.sin(a[1])
    y1 = a[2]*math.cos(a[3])
    y2 = a[2]*math.sin(a[3])
    z1 = x1*y1-x2*y2
    z2 = x1*y2+x2*y1
    if z1+0.005>=0 and z1<0:
        z1 = '0.00'
    else:
        z1 = '%.2f'%z1
    if z2+0.005>=0 and z2<0:
        z2 = '+0.00i'
    elif z2>=0:
        z2 = '+%.2fi'%z2
    else:
        z2 = '%.2fi'%z2
    print(z1+z2)
    

    总结:

    数列的片段和

    给定一个正数数列,我们可以从中截取任意的连续的几个数,称为片段。例如,给定数列 { 0.1, 0.2, 0.3, 0.4 },我们有 (0.1) (0.1, 0.2) (0.1, 0.2, 0.3) (0.1, 0.2, 0.3, 0.4) (0.2) (0.2, 0.3) (0.2, 0.3, 0.4) (0.3) (0.3, 0.4) (0.4) 这 10 个片段。

    给定正整数数列,求出全部片段包含的所有的数之和。如本例中 10 个片段总和是 0.1 + 0.3 + 0.6 + 1.0 + 0.2 + 0.5 + 0.9 + 0.3 + 0.7 + 0.4 = 5.0。

    输入格式:
    输入第一行给出一个不超过 10^​5的正整数 N,表示数列中数的个数,第二行给出 N 个不超过 1.0 的正数,是数列中的数,其间以空格分隔。

    输出格式:
    在一行中输出该序列所有片段包含的数之和,精确到小数点后 2 位。

    输入样例:

    4
    0.1 0.2 0.3 0.4
    

    输出样例:

    5.00
    

    思路
    这个题目很有意思,其实是一个找规律的题目,看上去很复杂,实际上如果动手写一写就可以展开发现规律。
    就拿案例来举例子:

    • 对0.1来说,0.1需要加的次数如下:
    • 0.1,(0.1,0.2),(0.1,0.2,0.3),(0.1,0.2,0.3,0.4),一共4次。
    • 对于0.2来说,0.2需要相加的次数如下:
    • 0.2,(0.1,0.2),(0.2,0.3),(0.1,0.2,0.3),(0.2,0.3,0.4),(0.1,0.2,0.3,0.4),一共6次。
    • 发现了没有什么规律?

    每个数出现的次数与它所在的位置是相关的!因为0.1左边没有数字,所以0.1只能放在开头,因此只有4种组合,同理,0.4右边没有数字,所以只能放在结尾,也是4种组合。

    因此我们可以根据数字所在的位置列出通式:

    出现次数为(i + 1) * (n - i)。
    但((i + 1) * (n - i))在运算过程中会发生溢出。就做了更改:
    先让arr 和 (i + 1)相乘,转化为double,再乘以(n - i)就可以避免溢出的问题了。
    

    因此求和直接用一条语句即可:

    sum = sum + ((i + 1) * arr * (n - i));
    

    大C的AC

    #include <stdio.h>
    int main(){
    	int n,i;
    	scanf("%d",&n);
    	double arr,sum;
    	for(i=0;i<n;i++){
    		scanf("%lf",&arr);
    		sum=sum+(arr*(n-i)*(i+1)); 
    	}
    	printf("%.2lf",sum);
    	return 0;
    }
    

    Java的伪AC

    //有两个测试点超时了
    import java.util.Scanner;
    
    public class Main {
    
    	public static void main(String[] args) {
    		@SuppressWarnings("resource")
    		Scanner in = new Scanner(System.in);
    		int n=in.nextInt();
    		double sum=0,arr;
    		for(int i=0;i<n;i++) {
    			arr=in.nextDouble();
    			sum=sum+(arr*(n-i)*(i+1));
    		}
    		System.out.printf("%.2f",sum);
    	}
    }
    

    python的AC

    n = int(input())
    m = [float(i) for i in input().split()]
    rst = 0
    for i in range(n):
        rst += m[i] * (n - i) * (i + 1)
    print('{:.2f}'.format(rst))
    
    

    整数转罗马数字

    罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

    字符          数值
    I             1
    V             5
    X             10
    L             50
    C             100
    D             500
    M             1000
    

    例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。

    通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

    • I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
    • X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
    • C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

    给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。

    示例 1:

    输入: 3
    输出: "III"
    

    示例 2:

    输入: 4
    输出: "IV"
    

    示例 3:

    输入: 9
    输出: "IX"
    

    示例 4:

    输入: 58
    输出: "LVIII"
    解释: L = 50, V = 5, III = 3.
    

    示例 5:

    输入: 1994
    输出: "MCMXCIV"
    解释: M = 1000, CM = 900, XC = 90, IV = 4.
    

    大C的初代

    #include <stdio.h>
    int main(){
    	int arr[13]={1000,900,500,400,100,90,50,40,10,9,5,4,1}; 
        char *str[13]={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
        int i,num;
        scanf("%d",&num);
        for(i=0;i<13;i++){
        	while(arr[i]<=num){
        		num=num-arr[i];
        		printf("%s",str[i]);
    		}
    	}
    	printf("
    ");
    	return 0;
    }
    

    大C的二代

    char * intToRoman(int num){
        char * prm[] = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
        int doc[] = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
        char * sam = (char *)malloc(sizeof(char)* 20);//生成一个动态字符数组20个够了
        int n = num;
        sam[0] = '';
            for(int i = 0; i < 13; i++) {
                while (n >= doc[i]) {
                    n-=doc[i];
                    strcat(sam,prm[i]);//把对应的罗马数字加入字符串中
                }
            }
        return sam;
    }
    

    JAVA的

    class Solution {
        public String intToRoman(int num) {
            int arr[]=new int[]{1000,900,500,400,100,90,50,40,10,9,5,4,1};
            String strs[]=new String[]{"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
            String str="";
            //从最大的开始算。
            for (int i = 0; i < 13; i++) {// >=的意思就是使用多个arr[i],比如3999,要有3个1000。	
    			 while(num>=arr[i]){ 
    				 num = num - arr[i]; 
    				 str = str + strs[i]; 
    				}
    			if (num == 0)   break;
    		}
    		return str;
    	}
    }
    

    python的

    class Solution:
        def intToRoman(self, num):
            number = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
            luoma = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I']
            shuru = ''
            for i in range(len(number)):
                while num >= number[i]:
                    num = num - number[i]
                    shuru = shuru + luoma[i]
            return shuru
    

    罗马数字转整数

    罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

    字符          数值
    I             1
    V             5
    X             10
    L             50
    C             100
    D             500
    M             1000
    

    例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。

    通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

    • I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
    • X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
    • C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

    给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。

    示例 1:

    输入: "III"
    输出: 3
    

    示例 2:

    输入: "IV"
    输出: 4
    

    示例 3:

    输入: "IX"
    输出: 9
    

    示例 4:

    输入: "LVIII"
    输出: 58
    解释: L = 50, V= 5, III = 3.
    

    示例 5:

    输入: "MCMXCIV"
    输出: 1994
    解释: M = 1000, CM = 900, XC = 90, IV = 4.
    

    思路

    • 定义一个双字母在前,单字母在后的String型数组,定义与之对应数字的数组,遍历s,先判断是否是双字母所代表的数字,再判断单字母所代表数字,将对应数字相加即可;

    JAVA的

    class Solution {
        public int romanToInt(String s) {
            String[] roman = { "IV", "IX", "XL", "XC", "CD", "CM", "I", "V", "X", "L", "C", "D", "M" };
            int[] nums = { 4, 9, 40, 90, 400, 900, 1, 5, 10, 50, 100, 500, 1000 };
            int num = 0;
            while (s.length() > 0) {
                for (int i = 0; i < roman.length; i++) {
                    if (s.startsWith(roman[i])) {
                        num += nums[i];
                        s = s.substring(roman[i].length());
                        break;
                    }
                }
            }
            return num;
        }
    }
    

    Python的

    class Solution:
        def romanToInt(self, s: str) -> int:
            d= {'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000}
            ans = 0
            for i in range(len(s)):
                if i < len(s) - 1 and d[s[i]] < d[s[i+1]]:
                    ans -= d[s[i]]
                else:
                    ans += d[s[i]]
            return ans
    
    欢迎查阅
  • 相关阅读:
    关于使用easyui dataGrid遇到的小bug问题
    构造带清除按钮的combo
    ajax方式提交数据时“+”的处理
    JavaScript call方法
    stackoverflow上的一个关于传递类对象的问题
    经典回溯算法(八皇后问题)
    c++构造函数(初始化式)被忽略的东西
    跟着<<C++Primer 学set容器>>
    排序算法(内部排序)总结
    hosts文件无法修改的问题解决方案
  • 原文地址:https://www.cnblogs.com/gh110/p/12158169.html
Copyright © 2020-2023  润新知