三、负数幂

image.png
负数的计算:(a + b i)(c + d i) = (ac - bd) + (bc + ad) i
然后计算就行了,不适用Cxx的形式,直接一次次乘就可以实现
其中使用大数,long无法储存

  1. import java.io.*;
  2. import java.math.BigInteger;
  3. public class Main {
  4. public static void main(String[] args) throws FileNotFoundException {
  5. PrintStream ps=new PrintStream(new FileOutputStream("work.txt"));
  6. System.setOut(ps); //文件输出
  7. int n=123456;
  8. BigInteger a=new BigInteger("2");
  9. BigInteger b=new BigInteger("3");
  10. BigInteger a1=new BigInteger("2");
  11. BigInteger b1=new BigInteger("3");
  12. for(int i=1;i<n;i++) {
  13. BigInteger ta=a;
  14. a=a.multiply(a1).subtract(b.multiply(b1));//a=a*a1-b*b1;
  15. b=ta.multiply(b1).add(b.multiply(a1));//b=a*b1+b*a1
  16. }
  17. System.out.println(a+(b.compareTo(BigInteger.ZERO)>0?"+":"-")+b+"i");
  18. }
  19. }

四、测试次数

类比于摔鸡蛋。
此处先写摔鸡蛋的例题问题。
https://blog.csdn.net/wolinxuebin/article/details/47057707
注意,此处是和二分查找不一样的。由于鸡蛋碎了就没了,所以不能二分
问题是100层楼2个鸡蛋
因此,我们先假设egg在x层要进行一个摔
如果没碎,就在 x+(x-1)层摔
如果碎了,在1到 x-1层中间遍历摔
(以上的情况是为了保证,对于任意的一个x,能保证一个大致的平衡(即左右都为需要有x-1个测试的)
最后得出一个公式 x + x-1 + x-2 + … + 1,当这个式子大于所要求的楼层总数时,才能解出。
所以求出x = 14(是进一法求)
第二个问题就是100层楼多个鸡蛋
设n个鸡蛋吧,那么用动态规划
理由同上。dp[鸡蛋个数+1][楼层数+1]
dp[m][n] = 1+ max(dp[m][n-k] , dp[m-1][n-1]) 其中k属于1到n-1,迭代遍历
前者是如果在n层没摔碎的话,就继续测试 n + n-1。我们前面为了保证平衡,左右次数其实是相同的,因此取1到 n-k,k次遍历
后者是如果摔碎了,就直接用n-1个鸡蛋的第n-1层楼的数据+1,(+1是因为已经摔碎了
(这里直接看代码更清楚

  1. public class Eggs{
  2. public int countMinSetp(int egg,int num){
  3. if(egg < 1 || num < 1) return 0;
  4. int[][] f = new int[egg+1][num+1];//代表egg个鸡蛋,从num楼层冷下来所需的最小的次数
  5. for(int i=1;i<=egg; i++){
  6. for(int j=1; j<=num; j++)
  7. f[i][j] = j;//初始化,最坏的步数
  8. }
  9. for(int n=2; n<=egg; n++){
  10. for(int m=1; m<=num; m++){
  11. for(int k=1; k<m; k++){
  12. //这里的DP的递推公式为f[n][m] = 1+max(f[n-1][k-1],f[n][m-k]) k属于[1,m-1]
  13. //从1-m层中随机抽出来一层k
  14. //如果第一个鸡蛋在k层碎了,那么我们将测试1~k-1层,就可以找出来,也即1+f[1][k-1]
  15. //如果第一个鸡蛋在k层没有碎,那么我们将测试k+1~m也即m-k层,
  16. // 这里也是重点!!!!
  17. // 现在我们手里有2个鸡蛋,要测试m-k层,那么我想问,
  18. //此时和你手里有2个鸡蛋要测试1~m-k层有什么区别?
  19. // 没有区别!是的在已知k层不碎的情况下,测试k+1~m层的方法和测试1~m-k没区别,
  20. //所以可以写成 1+f[n][m-k] 其中1表示为 在k层的那一次测试
  21. f[n][m] = Math.min(f[n][m],1+Math.max(f[n-1][k-1],f[n][m-k]));
  22. //这里前面是min的理由是要将结果最优
  23. //max是要保证一定能测出来
  24. }
  25. }
  26. }
  27. return f[egg][num];
  28. }
  29. public static void main(String[] args) {
  30. Eggs e = new Eggs();
  31. System.out.println(e.countMinSetp(2,100));
  32. }
  33. }

其中,Math.max(f[n-1][k-1],f[n][m-k]),max的原因是就是有可能破碎也有可能不碎,为了保证能够测出来,必须要取最大的。

那么现在再看手机问题,其实本质是一样的,其中只要设置n = 3 ,层数 = 1000即可

六、递增三元组

image.png
算法思路:先把三个数组都排序(可以调用库函数),然后只遍历b数组,由于b数组最特殊。
b数组最为特别,因为一个数组要比它小,C数组要比它大
那么总和就是每个b中的元素在a数组中小于这个元素的*在c数组中大于b数组这个元素的个数

  1. import java.util.Arrays;
  2. import java.util.Comparator;
  3. import java.util.Scanner;
  4. public class T6 {
  5. public static void main(String[] args) {
  6. //首先是输入
  7. Scanner sc = new Scanner(System.in);
  8. int n = sc.nextInt();
  9. int[] a = new int[n];
  10. Integer[] b = new Integer[n];
  11. Integer[] c = new Integer[n];
  12. for (int i = 0; i < n; i++) {
  13. a[i] = sc.nextInt();
  14. }
  15. for (int i = 0; i < n; i++) {
  16. b[i] = sc.nextInt();
  17. }
  18. for (int i = 0; i < n; i++) {
  19. c[i] = sc.nextInt();
  20. }
  21. //对b进行遍历
  22. Arrays.sort(a);//默认从小到大
  23. Arrays.sort(b, new cmp());
  24. Arrays.sort(c, new cmp());
  25. int ans = 0;
  26. //要求是a<b<c
  27. for (int i = 0; i < n; i++) {
  28. //如果a>b,就不比较了,直接跳出,此时j的数就是符合的数。
  29. int j = 0;
  30. for (j = 0; j < n; j++) {
  31. if (a[j] >= b[i]) {
  32. break;
  33. }
  34. }
  35. int k = 0;
  36. for (k = 0; k < n; k++) {
  37. if (c[k] <= b[i]) {
  38. break;
  39. }
  40. }
  41. ans += j * k;
  42. }
  43. System.out.println(ans);
  44. }
  45. }
  46. class cmp implements Comparator<Integer> {
  47. @Override
  48. public int compare(Integer o1, Integer o2) {
  49. return o2 - o1;
  50. }
  51. }

七、螺旋折线

image.png
image.png
两种解法:
第一种:https://blog.csdn.net/qq799028706/article/details/84312062
巧算
第二种自己算的:

  1. public class T7 {
  2. public static void main(String[] args) {
  3. Scanner sc = new Scanner(System.in);
  4. int x = sc.nextInt();
  5. int y = sc.nextInt();
  6. int n = Math.max(Math.abs(x), Math.abs(y));//最大值
  7. //直接算就行了
  8. int ans = (2 * n - 1) * (2 * n - 2);
  9. //就是是x轴较大
  10. if (n == Math.abs(x)) {
  11. //右边的竖线
  12. if (x > 0) {
  13. ans = ans + 2 * (2 * n - 1) + 2 * n + n - y;
  14. }else
  15. //左边的竖线
  16. ans = ans+ 2 * n - 1 + y+(n-1);
  17. }else {
  18. //是y轴比较大,算横坐标
  19. //上面横线
  20. if (y >0){
  21. ans = ans + 2 * (2 * n - 1) + x+n;
  22. }else
  23. //下面横线
  24. ans = ans + n-x;
  25. }
  26. System.out.println(ans);
  27. }
  28. }