1.小强现在有n个物品,每个物品有x,y两种属性和.他想要从中挑出尽可能多的物品满足以下条件:对于任意两个物品 i 和 j ,满足( i.x < j.x 且 i.y < j.y)或者(i.x > j.x 且 i.y > j.y).问最多能挑出多少物品
第一行输入一个正整数 T.表示有T组数据.
对于每组数据,第一行输入一个正整数N.表示物品个数N.
接下来两行,每行有个N整数.
第一行表示N个节点的X属性.
第二行表示N个节点的Y属性
题解:https://blog.youkuaiyun.com/xyjy11/article/details/118032689
2.小强发现当已知xy=B以及x+y=A时,能很轻易的算出的值.但小强想请你在已知 A和B的情况下,计算出x^n+y^n的值.因为这个结果可能很大,所以所有的运算都在模1e9+7下进行.
输入例子1:
3
4 4 3
2 3 4
5 2 6
输出例子1:
16
999999993
9009
import java.util.*;
public class Main{
/**
* 阿里2 已知 x+y=A xy = B 求x^n+y^n
* 递推式 xn = Axn-1 - Bxn-2
*/
static long mod = (long)Math.pow(10,9)+7;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int m = in.nextInt();
for(int i=0;i<m;i++){
long a = in.nextInt();
long b = in.nextInt();
int n = in.nextInt();
a %= mod;
b %= mod;
System.out.println(solve(a,b,n));
}
}
public static long solve(long a, long b,int n){
long[] nums = new long[n+1];
nums[1] = a;
if(n==1) return nums[1]; //1次方直接等于A
nums[2] = (a * a % mod - 2 * b % mod + mod) % mod;
if(n==2) return nums[2];
for(int i=3;i<=n;i++)
nums[i] = ((a*nums[i-1]%mod)-(b*nums[i-2]%mod)+mod)%mod;
return nums[n];
}
}
主要理解当n大于3之后的递推关系;
补充:Math.pow(a,3)表示a的三次方;
3. 小强现在n有个节点,他想请你帮他计算出有多少种不同的二叉树满足节点个数为且树的高度不超过m的方案.因为答案很大,所以答案需要模上1e9+7后输出.
树的高度: 定义为所有叶子到根路径上节点个数的最大值.
例如: 当n=3,m=3时,有如下5种方案:
动态规划题解:
import java.util.*;
public class Main{
public static final int MOD = 1000000007;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
// dp[i][j]表示i个节点最大深度为j的树数量
long[][] dp = new long[n+1][m+1];
Arrays.fill(dp[0], 1);
for(int i = 1; i <= n; i++) { //节点数
for(int j = 1; j <= m; j++) { //层数
for(int k = 0; k < i; k++) {
// 左子树节点数为k,右子树节点数为i-k-1,且左右子树都要求小于等于j-1
dp[i][j] = (dp[i][j] + dp[k][j-1] * dp[i-k-1][j-1] % MOD) % MOD;
}
}
}
System.out.println(dp[n][m]);
}
}
4. 小强想要从[1,A]中选出一个整数x,从[1,B]中选出一个整数y .使得满足x/y = a/b的同时且x和y的乘积最大。如果不存在这样的x和y,请输出“ 0 0”.
输入描述:
输入一行包含四个整数A,B,a和b.
1≤A,B,a,b≤2e9
输出描述:
输出两个整数表示满足条件的x和y.若不存在,则输出"0 0".
例子1:
输入:1 1 2 1 输出:0 0
例子2:
输入: 1000 500 4 2 输出:1000 500
解题思路:因为a和b是自己提供的所以可以求出a b 的最大公约数c,然后将需要求解的
x初始化为a/c;y初始化为b/c;
就是x=a/c;y=a/c;然后每次x再去加上a/c,y也再去加上a/c;保证x/y=a/b成立
其中求最大公约数的算法:辗转除;
// 辗转相除法求解最大公约数
// 两个正整数a b (a>b) 的最大公约数 等于 a除以b的余数 c 和 b 之间的最大公约数
public static int GCD(int a, int b) {
int c = 0;
while(b != 0) {
c = a % b;
a = b;
b = c;
}
return a;
}
完整代码
import java.util.*;
// java int 类整数的最大值是 2 的 31 次方 - 1 = 2147483648 - 1 = 2147483647
// long类型的数据范围-2的63次方 ~ 2的63次方-1,即 -9223372036854775808 ~ 9223372036854775807
public class Alibaba_4 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
int A = sc.nextInt();
int B = sc.nextInt();
int a = sc.nextInt();
int b = sc.nextInt();
// 首先求解a与b的最大公约数 Greatest Common Divisor(GCD)
int c = GCD(a, b);
// System.out.println(c);
// 相当于约分处理,简化
a = a / c;
b = b / c;
long x, y;
// 判断是否存在x、y
if(A < a || B < b) {
x = 0;
y = 0;
}else {
x = a;
y = b;
while(x + a <= A && y + b <= B) {
x += a;
y += b;
}
}
System.out.println(x+" "+y);
}
sc.close();
}
// 辗转相除法求解最大公约数
// 两个正整数a b (a>b) 的最大公约数 等于 a除以b的余数 c 和 b 之间的最大公约数
public static int GCD(int a, int b) {
int c = 0;
while(b != 0) {
c = a % b;
a = b;
b = c;
}
return a;
}
}
5.在一张2D地图上小强有n座房子,因为地理位置的原因没有办法给每座房子提供水源,所以小强打算修建一条平行y轴的水渠。因为这条水渠无限长,所以能够看做是一条平行于y轴的直线。现在小强想确定修建水渠的位置,能够使得这n座房子到水渠的垂直距离和最小,请你输出最小的距离和。
输入描述:
第一行输入一个正整数n.
接下来n行,每行输入两个正整数xi,yi,分别表示每个房子所在的二维坐标.
1000000≤xi,yi≤100000
1≤n≤100000
输出描述:
输出一个整数表示答案
解题思路:因为水渠平行于y轴所以只需要找出所有xi的中位数即可。然后所有xi-中位数之和就是结果。
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
public class Alibaba_5 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(); //房子数目
int[][] house = new int [n][2];
for (int i = 0; i < n; i++) {
house[i][0] = sc.nextInt();
house[i][1] = sc.nextInt(); // 也可以不读入这个数据
}
Arrays.sort(house, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[0] - o2[0];
}
});
// 存放距离,注意数据溢出
long res = 0;
// 求解中位数,作为水渠的位置
double mid_location = n % 2 == 1? house[(n-1)/2][0]: (house[n/2 - 1][0] + house[n/2][0]) / 2;
//求解距离和
for(int i = 0; i < n; i ++) {
res += Math.abs(house[i][0] - mid_location);
}
System.out.println(res);
}
}
6.最近小强主办了一场国际交流会,大家在会上以一个圆桌围坐在一起。由于大会的目的就是让不同国家的人感受一下不同的异域气息,为了更好地达到这个目的,小强希望最大化邻座两人之间的差异程度和。为此,他找到了你,希望你能给他安排一下座位,达到邻座之间的差异之和最大。
输入描述:
输入总共两行。
第一行一个正整数n,代表参加国际交流会的人数(即圆桌上所坐的总人数,不单独对牛牛进行区分)
第二行包含n个正整数,第i个正整数ai代表第i个人的特征值。
其中3 ≤ n ≤ 10^5, 1 ≤ ai ≤ 10^9 (注意数据溢出)
注意:邻座的定义为: 第i人(1<i<n)的邻座为i-1,i+1,第1人的邻座是2,n,第n人的邻座是1,n-1。
邻座i,j的差异值计算方法为|ai-aj|。
每对邻座差异值只计算一次。
输出描述:
输出总共两行。
第一行输出最大的差异值。
第二行输出用空格隔开的n个数,为重新排列过的特征值。(注意:不输出编号)
如果最大差异值情况下有多组解,输出任意一组即可。
输入
4
3 6 2 9
输出
20
6 2 9 3
说明
这么做的话,差异和为|6−2∣+∣2−9∣+∣9−3∣+∣3−6∣= 20为最大的情况。
解题思路:
大体思路:数组排序,计算数组前后(0,n-1)+(1,n-2).....
将数组排序,新建resultArr存储最终结果。定义left和right指定到排序后的左和右。循环排序后的数组,通过i%2==0来判断是left放进还是right放进去,然后计算数组前后中前后差值。循环结束加上最后一位到头位置的差值(环)就为总和。
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
public class Alibaba_6 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(); //人数
long[] terms = new long[n];
for (int i = 0; i < n; i++){
terms[i] = sc.nextInt(); //特征值
}
Arrays.sort(terms);
// 声明一个输出空间
long[] resultArr = new long[n];
long reslutSum = 0;
int left = 0;
int right = n - 1;
for (int i = 0; i < n; i++){
if(i%2==0){
resultArr[i] = terms[left];
left++;
}else {
resultArr[i] = terms[right];
right--;
}
if(i>0) reslutSum = reslutSum + Math.abs(resultArr[i]-resultArr[i-1]);
}
//计算最后一位与第一位的差值
reslutSum = reslutSum + Math.abs(resultArr[n-1]-resultArr[0]);
//输出结果
System.out.println(reslutSum);
for (long result : resultArr) {
System.out.print(result + " ");
}
}
}