拼多多5月6日 后端笔试题 第四题
因为是竞赛题所以大部分都是C++的,我用Java写了一遍。
【题意】
给出一个长度在 100 000 以内的正整数序列,大小不超过 1012 求一个连续子序列,使得在所有的连续子序列中,它们的gcd值乘以它们的长度最大
输入
6
5 8 6 2 6 8
输出
10
第一轮:
从最后的8开始
使用栈1 栈2
8 :5 入栈1,8入栈2;
6 8 :求6和8的公约数 为2 ,2<8;4 入栈1 2入栈2;
2 6 8 :求2 和 栈顶 2 的公约数 ,2 == 2 ;4出栈1 3入栈1(此处替换了栈1的栈顶);
6 2 6 8:6和栈顶2的公约数 , 2 == 2; 3出栈1,2入栈1(替换);
8 6 2 6 8: 8和栈顶2的公约数,2==2; 2出栈1,1入栈1;
5 8 6 2 6 8 : 5和栈顶2的公约数 1!=2 ;0入栈1, 1入栈2;
两个栈同时出栈,得到当前长度*公约数,当前长度计算见代码。
import java.util.Scanner; import java.util.Stack; public class Pdd2020S4 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N = sc.nextInt(); int [] temp = new int[N]; for(int i=0;i<N;i++){ temp[i] = sc.nextInt(); } //最终结果 int res =0; //从最右端开始 for(int i=N-1;i>=0;i--){ Stack <Integer> stack1 = new Stack(); Stack <Integer> stack2 = new Stack(); //从最右端开始 for(int j=i;j>=0;j--){ if(stack1.isEmpty()){ stack1.push(j); stack2.push(temp[j]); }else{ int preG = stack2.peek(); //借用上次计算的公约数,计算右移一位的公约数 int curG = gcd(temp[j],preG%temp[j]); //若公约数相等便更新起始点 if(preG==curG){ stack1.pop(); stack1.push(j); //若公约数小于原来 则新增 }else if(curG<preG){ stack1.push(j); stack2.push(curG); } } } //出栈计算结果 while (!stack1.isEmpty()){ res = Math.max(res,(i-stack1.pop()+1)*stack2.pop()); } } System.out.println(res); } //调用之前进行 b%a; //要求a>b;在之前做b%a public static int gcd(int a,int b){ return b==0?a:gcd(b,a%b); } }
虽然是暴力解题,但是在计算公约数的时候还是取了巧,以及中间过程的计算。有不对的地方请多指教,包括代码规范。