丰收
题目描述 又到了丰收的季节,恰逢小易去牛牛的果园里游玩。 牛牛常说他对整个果园的每个地方都了如指掌,小易不太相信,所以他想考考牛牛。 在果园里有N堆苹果,每堆苹果的数量为ai,小易希望知道从左往右数第x个苹果是属于哪一堆的。 牛牛觉得这个问题太简单,所以希望你来替他回答。 输入描述: 第一行一个数n(1 <= n <= 105)。 第二行n个数ai(1 <= ai <= 1000),表示从左往右数第i堆有多少苹果 第三行一个数m(1 <= m <= 105),表示有m次询问。 第四行m个数qi,表示小易希望知道第qi个苹果属于哪一堆。 输出描述: m行,第i行输出第qi个苹果属于哪一堆。
代码语言:javascript复制5
2 7 3 4 9
3
1 25 11
1
5
3
代码语言:javascript复制import java.util.*;
public class Main {
// 思路 ,依次求出累加和二分查找找出大于他的第一个数
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int n=in.nextInt();
int[] d = new int[n];
d[0] = in.nextInt();
for(int i=1;i<n;i ){
d[i] = in.nextInt() d[i-1];
}
int m = in.nextInt();
for (int i=0;i<m;i ){
int x = in.nextInt();
int left = 0, right = n;
while (left < right){
int mid = left (right - left)/2;
if(d[mid] < x){
left = mid 1;
}else {
right = mid;
}
}
System.out.println(left 1);
}
}
}
整理房间
又到了周末,小易的房间乱得一团糟。 他希望将地上的杂物稍微整理下,使每团杂物看起来都紧凑一些,没有那么乱。 地上一共有n团杂物,每团杂物都包含4个物品。第i物品的坐标用(ai,bi)表示,小易每次都可以将它绕着(xi,yi)逆时针旋转90^ circ90 ∘ ,这将消耗他的一次移动次数。如果一团杂物的4个点构成了一个面积不为0的正方形,我们说它是紧凑的。 因为小易很懒,所以他希望你帮助他计算一下每团杂物最少需要多少步移动能使它变得紧凑。
输入描述: 第一行一个数n(1 <= n <= 100),表示杂物的团数。 接下来4n行,每4行表示一团杂物,每行4个数ai, bi,xi, yi, (-104 <= xi, yi, ai, bi <= 104),表示第i个物品旋转的它本身的坐标和中心点坐标。
输出描述: n行,每行1个数,表示最少移动次数。
代码语言:javascript复制4
1 1 0 0
-1 1 0 0
-1 1 0 0
1 -1 0 0
1 1 0 0
-2 1 0 0
-1 1 0 0
1 -1 0 0
1 1 0 0
-1 1 0 0
-1 1 0 0
-1 1 0 0
2 2 0 1
-1 0 0 -2
3 0 0 -2
-1 1 -2 0
1
-1
3
3
首先 一个点逆时针旋转,如果是绕原点进行旋转,那么画图可以得出 旋转后的点(-y,x), 那么同理按照(a,b)进行旋转就是(a-y,b x)所以求出x,y 值就是旋转后的位置点
题中: xx = a - (y - b) yy = b (x - a)
然后要解决是判断是否是正方形
首先需要对四个点进行排序,按照横纵坐标排序,保证点正确位置,这里一定要注意排序后边与边的相邻关系
求出各个点间的距离,保证四个边相等,同时保证不是平行四边形,保证一个直角,其次是,保证表距离不为0
最小,依次对四个点进行旋转尝试,并通过
count = min(count, m n p q);
求最小值
代码语言:javascript复制import java.util.*;
public class Main {
// 思路 进行依次尝试旋转,这里是因为每一个旋转最多3次,所以直接枚举即可
static class Point implements Comparable<Point>{
int x;
int y;
int a;
int b;
public Point(int x,int y,int a,int b){
this.x = x;
this.y = y;
this.a = a;
this.b = b;
}
@Override
public int compareTo(Point o) {
if(x == o.x){
return y - o.y;
}
return x - o.x;
}
}
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int n=in.nextInt();
Point[] points = new Point[4];
for(int i=0;i<n;i ){
for (int j = 0;j<4;j ){
int x = in.nextInt();
int y = in.nextInt();
int a = in.nextInt();
int b = in.nextInt();
points[j] = new Point(x,y,a,b);
}
int count = movingCount(points);
System.out.println(count);
}
}
private static int movingCount(Point[] points) {
// 每一个点要旋转的次数可以 0 ~ 3
// 最多的次数不会超过16;
int count = 16;
for(int i=0;i<4;i ){
for(int j=0;j<4;j ){
for(int p=0;p<4;p ){
for(int q=0;q<4;q ){
if(isSqare(rotate(points[0],i),rotate(points[1],j),rotate(points[2],p),rotate(points[3],q))){
count = Math.min(count,i j p q);
}
}
}
}
}
return count == 16?-1:count;
}
public static Point rotate(Point p,int t){
int x = p.x;int y = p.y;int a = p.a;int b = p.b;
int xx,yy;
for (int i=0;i<t;i ){
xx = a - (y - b);
yy = b (x - a);
x = xx;
y = yy;
}
return new Point(x,y,a,b);
}
private static boolean isSqare(Point a,Point b,Point c,Point d) {
Point[] points = new Point[4];
points[0] = a;points[1] = b;points[2] = c;points[3] = d;
Arrays.sort(points);
// 得到四个点间距离
int d1 = distance(points[0],points[1]);
int d2 = distance(points[0],points[2]);
int d3 = distance(points[1],points[3]);
int d4 = distance(points[3],points[2]);
if(d1 != 0 && d1 == d2 && d2 == d3 && d3 == d4 && isRightAngle(points[0],points[1],points[2])){
return true;
}else {
return false;
}
}
private static boolean isRightAngle(Point p1, Point p2, Point p3) {
int x = (p1.x - p2.x)*(p1.x - p3.x) (p1.y - p2.y)*(p1.y - p3.y);
if (x == 0) {
return true;
}
return false;
}
public static int distance(Point a, Point b){
return (a.x - b.x)*(a.x - b.x) (a.y - b.y) * (a.y-b.y);
}
}
表达式求值
今天上课,老师教了小易怎么计算加法和乘法,乘法的优先级大于加法,但是如果一个运算加了括号,那么它的优先级是最高的。例如: 1 23=7 1(2 3)=5 123=6 (1 2)3=9 现在小易希望你帮他计算给定3个数a,b,c,在它们中间添加" ", "", "(", ")"符号,能够获得的最大值。 输入描述: 一行三个数a,b,c (1 <= a, b, c <= 10)
代码语言:javascript复制1 2 3
9
代码语言:javascript复制package com.bupt.learn;
import java.util.*;
public class Main {
// 表达式求值,思路在其中添加乘加同时可以随时进行弹出计算来表示加括号
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 只有三个数的情况下不要考虑太复杂
// 因为只有 * 和 ,最大的数是
int a = in.nextInt();
int b = in.nextInt();
int c = in.nextInt();
int count;
if(a * b > a b){
count = a*b;
}else {
count = a b;
}
if(c > 1){
System.out.println(c * count);
}else {
System.out.println(c count);
}
}
}
加括号在这里只是表面 和 * 是同等的权重,无在乎优先级
从 i,j 数的最大值 dp[i][j] = max(dp[i][k] dp[k 1][j],dp[i][k] * dp[k 1][j],dp[i][j])
代码语言:javascript复制import java.util.*;
public class Main {
// 表达式求值,思路在其中添加乘加同时可以随时进行弹出计算来表示加括号
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 只有三个数的情况下不要考虑太复杂
// 因为只有 * 和 ,最大的数是
int[][] dp = new int[3][3];
for (int i=0;i<3;i ){
dp[i][i] = in.nextInt();
}
for(int i=0;i<3;i ){
for(int j=0;j<3;j ){
for(int k =i;k<j;k ){
dp[i][j] = Math.max(dp[i][j],Math.max(dp[i][k] dp[k 1][j],dp[i][k] * dp[k 1][j]));
}
}
}
System.out.println(dp[0][2]);
}
}
塔
小易有一些立方体,每个立方体的边长为1,他用这些立方体搭了一些塔。 现在小易定义:这些塔的不稳定值为它们之中最高的塔与最低的塔的高度差。 小易想让这些塔尽量稳定,所以他进行了如下操作:每次从某座塔上取下一块立方体,并把它放到另一座塔上。 注意,小易不会把立方体放到它原本的那座塔上,因为他认为这样毫无意义。 现在小易想要知道,他进行了不超过k次操作之后,不稳定值最小是多少。 输入描述: 第一行两个数n,k (1 <= n <= 100, 0 <= k <= 1000)表示塔的数量以及最多操作的次数。 第二行n个数,ai(1 <= ai <= 104)表示第i座塔的初始高度。 输出描述: 第一行两个数s, m,表示最小的不稳定值和操作次数(m <= k) 接下来m行,每行两个数x,y表示从第x座塔上取下一块立方体放到第y座塔上。
代码语言:javascript复制3 2
5 8 5
0 2
2 1
2 3
代码语言:javascript复制import java.util.*;
public class Main {
// 塔,优化的结果是所有的数都一样达到平均值,
// 算法的思路,将数列进行排序,从大到小,将大--,小 ,到达平均值 进行移动
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int k = in.nextInt();
List<Integer> towers = new ArrayList<>();
for (int i=0;i<n;i ){
towers.add(in.nextInt());
}
int count = 0;
int max = Collections.max(towers);
int min = Collections.min(towers);
List<Integer> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
while (max - min > 1 && count < k){
max = Collections.max(towers);
min = Collections.min(towers);
list1.add(towers.indexOf(max) 1);list2.add(towers.indexOf(min) 1);
towers.set(towers.indexOf(min),min 1);
towers.set(towers.indexOf(max),max-1);
count ;
}
System.out.println(Collections.max(towers)-Collections.min(towers) " " count);
for (int i=0;i<list1.size();i )
{
System.out.println(list1.get(i) " " list2.get(i));
}
}
}
小易的字典
题目描述 小易在学校中学习了关于字符串的理论, 于是他基于此完成了一个字典的项目。
小易的这个字典很奇特, 字典内的每个单词都包含n个'a'和m个'z', 并且所有单词按照字典序排列。
小易现在希望你能帮他找出第k个单词是什么。
输入描述: 输入包括一行三个整数n, m, k(1 <= n, m <= 100, 1 <= k <= 109), 以空格分割。
输出描述: 输出第k个字典中的字符串,如果无解,输出-1。
代码语言:javascript复制2 2 6
zzaa
直接dfs生成第k个排列时间复杂度太大,没有利用到只有两个元素的特性
代码语言:javascript复制package com.bupt.learn;
import java.util.*;
public class Main {
// 塔,优化的结果是所有的数都一样达到平均值,
// 算法的思路,将数列进行排序,从大到小,将大--,小 ,到达平均值 进行移动
static int count = 0;
static boolean flag = false;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
int k = in.nextInt();
// 生成第k个序列
StringBuilder sb = new StringBuilder();
for (int i=0;i<n;i ){
sb.append("a");
}
for (int i=0;i<m;i ){
sb.append("z");
}
permutation(k,"",sb.toString(),new HashSet<String>());
if (!flag){
System.out.println(-1);
}
}
public static void permutation(int k,String prefix, String arr,HashSet<String> set){
if(prefix.length() == arr.length()){
if(set.contains(prefix)){
return;
}
set.add(prefix);
count ;
if(count == k){
flag = true;
System.out.println(prefix);
}
return;
}
for(char c:arr.toCharArray()){
if(countChar(c,prefix) < countChar(c,arr)){
permutation(k, prefix c,arr,set);
}
}
}
private static int countChar(char c, String str) {
int count = 0;
for(char ch : str.toCharArray()){
if (ch == c){
count ;
}
}
return count;
}
}
因为只有两个元素,计算i个a,j个z一共生成多少个排列
代码语言:javascript复制 import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int m = scan.nextInt();//a的个数
int n = scan.nextInt();//z的个数
long target = scan.nextInt();//目标第几个
long k =0;
ArrayList<String> list = new ArrayList<String>();
while(m>0&&n>0) {//当a和z均存在时执行
k = pz(m-1,n,target);//假设a确定,出去a之后剩余a和z的排列组合个数
if(k>=target) {//如果确定a之后,剩余的排列组合数大于目标,则说明a已确定
list.add("a");
m--;//a的个数减1
}else {//如果确定a之后,剩余的排列组合数小于目标,则说明不是a。
list.add("z");
n--;//z的个数减1
target -= k;//目标减掉排列组合数。因为如果a开头可以有k中情况,
//减掉k之后即为确定z开头之后,接下来找第target个即可。
}
}
if(target != 1) {//存在经过计算之后必为1
System.out.println("-1");
return;
}else {
while(m>0) {//如果z的个数为0,则将a追加到最后即可
list.add("a");
m--;
}
while(n>0) {//如果a的个数为0,则将z追加到最后即可
list.add("z");
n--;
}
}
for (int i = 0; i < list.size(); i ) {
System.out.print(list.get(i));
}
}
public static long pz(int m,int n,long target) {//计算假设a确定之后,a之后的部分排列组合数
if(m==0||n==0)
return 1;
long sum = m n;
long k = 1;
n = Math.min(m, n);//C(m n) n=C(m n) m 取最小即可
for (int i = 0; i < n ; i ) {
k *= sum-i;
k /= (i 1);
if(k>target)//防止大数。如果k>target 则只进行list.add("a")和m--//a的个数减1。
//没有target -= k;因此不影响
break;
}
return k;
}
}