【LQ系列】 BASIC-16~BASIC-19

今天做到了VIP部分的题,感觉难度上和之前明显有一个小的跨越,目前卡在了第今天的第五题上,所以今天我只做了四道题,明天会补上第五题。其中有些题我参照了其他博友们的代码,感觉大神的代码真的很赞,自己还需努力啊~~好了废话不多说,开始今天的四道题:


【BASIC-16】 基础练习 分解质因数 


问题描述
  求出区间[a,b]中所有整数的质因数分解。
输入格式
  输入两个整数a,b。
输出格式
  每行输出一个数的分解,形如k=a1*a2*a3...(a1<=a2<=a3...,k也是从小到大的)(具体可看样例)
样例输入
3 10
样例输出
3=3
4=2*2
5=5
6=2*3
7=7
8=2*2*2
9=3*3
10=2*5
提示
  先筛出所有素数,然后再分解。
数据规模和约定
  2<=a<=b<=10000


Code:

import java.util.Scanner ;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner( System.in ) ;
		int a= sc.nextInt() ;
		int b = sc.nextInt() ;
		int i = 2 ;	// 考虑分解质因数时从而开始考虑
		String result = "" ;
		// 当起始为 1 时特殊考虑
		if( a == 1 ) {
			result += "1=1" ;
			a ++ ;
		}
		for( int k = a; k <= b; k ++ ) {	// k为被分解质因数
			result= k + "=" ;	// 存储分解表达式
			i = 2 ;		// 每次判断新的 k 要重置当前考虑的质因数
			int temp = k ;	// 充当 k 的替身,以免除 i 时修改了循环变量的值导致不断循环
			while(  i <= k ) {	// 如果k能除开当前考虑的质因数
				if( temp % i == 0 ) {		// 这里偷了懒,本来应该是先构造[a,b]之间的质数表,然后让 i 从前往后取,但是这里没有,当 temp % 2 != 0 后,当判断 temp % 4 一定也不为0,所以这里可能会多几次循环,但却减少了构造质数表的时间
					result += i + "*" ;
					temp /= i ;
				}
				else {	// 如果k除不开当前考虑的质因数,则换下一位
					i ++ ;
				}
			}
			System.out.println( result.substring(0, result.length()-1) );	// 因为最后一位多保存了一位 '*' ,所以这里输出取个子串
		}
	}

}


【BASIC-17】 基础练习 矩阵乘法 


问题描述
  给定一个N阶矩阵A,输出A的M次幂(M是非负整数)
  例如:
  A =
  1 2
  3 4
  A的2次幂
  7 10
  15 22
输入格式
  第一行是一个正整数N、M(1<=N<=30, 0<=M<=5),表示矩阵A的阶数和要求的幂数
  接下来N行,每行N个绝对值不超过10的非负整数,描述矩阵A的值
输出格式
  输出共N行,每行N个整数,表示A的M次幂所对应的矩阵。相邻的数之间用一个空格隔开
样例输入
2 2
1 2
3 4
样例输出
7 10
15 22


Code:

import java.util.Scanner ;

public class Main {

	public static void matrix_multi ( long[][] A, long[][] B, long[][] result, int M, int N ) {	// result 记录每次A*B的结果
		if( M < 2 ) 
			return ;
		for( int i = 0; i < N; i ++ ) {		// i:表示 result 的行
			for( int j = 0; j < N; j ++ ) {	// j:表示 result 的列,对于A行数即是列数
				result[i][j] = 0 ;
				for( int k = 0; k < N; k ++ )	{ 	// k: 表示 A1 的列和 A2 的行
					result[i][j] += A[i][k] * B[k][j] ;
				}
			}
		}
		for( int i = 0; i < N; i++ )
				A[i] = result[i].clone() ;
		matrix_multi( A, B, result, M - 1, N ) ;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner( System.in ) ;
		int N = sc.nextInt() ;	// 输入矩阵的阶数
		int M = sc.nextInt() ;	// 输入要求的幂数
		long[][] A = new long[N][N] ;
		long[][] result = new long[N][N] ;
		for( int i = 0; i < N; i ++ ) {
			for( int j = 0; j < N; j++ ) {
				A[i][j] = sc.nextInt() ;
				result[i][j] = 0 ;
			}
		}
		// 0次幂特殊处理
		if( M == 0 ) {
			for( int i = 0; i < N; i ++ ) {
				for( int j = 0; j < N; j++ ) {
					if( i == j )
						result[i][j] = 1 ;	
					else
						result[i][j] = 0 ;
				}
			}
		}
		// 1次幂直接赋值
		else if( M == 1 ) {
			for( int i = 0; i < N; i ++ ) {
				for( int j = 0; j < N; j++ ) {
					result[i][j] = A[i][j] ;
				}
			}
		}
		// 多次幂处理
		else
			matrix_multi( A, A.clone(), result,  M, N ) ;	// 注意:这里第二个参数一定要是A.clone(),因为否则在函数处理中A和B总是指向同一块栈空间
		
		for( int i = 0; i < N; i ++ ) {
			for( int j = 0; j < N; j++ ) {
				System.out.print( result[i][j] + " " );
			}
			System.out.println();
		}
	}

}


【BASIC-18】 基础练习 矩形面积交


问题描述
  平面上有两个矩形,它们的边平行于直角坐标系的X轴或Y轴。对于每个矩形,我们给出它的一对相对顶点的坐标,请你编程算出两个矩形的交的面积。
输入格式
  输入仅包含两行,每行描述一个矩形。
  在每行中,给出矩形的一对相对顶点的坐标,每个点的坐标都用两个绝对值不超过10^7的实数表示。
输出格式
  输出仅包含一个实数,为交的面积,保留到小数后两位。
样例输入
1 1 3 3
2 2 4 4
样例输出
1.00


Code:


import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.Scanner ;

public class Main {

	// 求第二大
	public static double s_max( double x1, double x2, double x3, double x4 ) {
		double[] a = {x1, x2, x3, x4} ;
		Arrays.sort(a) ;
		return a[1] ;
	}
	
	// 求第二小
	public static double s_min( double x1, double x2, double x3, double x4 ) {
		double[] a = {x1, x2, x3, x4} ;
		Arrays.sort(a) ;
		return a[2] ;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner( System.in ) ;
		// 输入第一个矩形的左下点坐标
		double x1 = sc.nextDouble() ;
		double y1 = sc.nextDouble() ;
		// 输入第一个矩形的右上点坐标
		double x2 = sc.nextDouble() ;
		double y2 = sc.nextDouble() ;
		// 输入第二个矩形的右上点坐标
		double x3 = sc.nextDouble() ;
		double y3 = sc.nextDouble() ;
		// 输入第二个矩形的左下点坐标
		double x4 = sc.nextDouble() ;
		double y4 = sc.nextDouble() ;
		// 取绝对值
		x1 = Math.abs(x1) ;
		y1 = Math.abs(y1) ;
		x2 = Math.abs(x2) ;
		y2 = Math.abs(y2) ;
		x3 = Math.abs(x3) ;
		y3 = Math.abs(y3) ;
		x4 = Math.abs(x4) ;
		y4 = Math.abs(y4) ;
		// 格式控制
		NumberFormat formatter = new DecimalFormat( "#0.00" ) ;
		
		double result ;
		// 不相交
		if( Math.max(x1, x2) <=Math.min(x3, x4) ||
				Math.min(x1, x2) >= Math.max(x3, x4) || 
				Math.min(y1, y2) >= Math.max(y3, y4) ||
				Math.max(y1, y2) <= Math.min(y3, y4) ) {
			result = 0.0 ;
		}
		// 相交,则等于中间两个点的坐标为对顶点的矩形面积
		else {
			result = Math.abs( (s_max(x1, x2, x3, x4) - s_min(x1, x2, x3, x4)) * 
					(s_max(y1, y2, y3, y4) - (s_min(y1, y2, y3, y4) ))) ;
		}
		System.out.println( formatter.format(result) );
	
	}

}


【BASIC-19】 基础练习 完美的代价 


问题描述
  回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
  交换的定义是:交换两个相邻的字符
  例如mamad
  第一次交换 ad : mamda
  第二次交换 md : madma
  第三次交换 ma : madam (回文!完美!)
输入格式
  第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
  第二行是一个字符串,长度为N.只包含小写字母
输出格式
  如果可能,输出最少的交换次数。
  否则输出Impossible
样例输入
5
mamad
样例输出
3


【此题参考了其他博友的代码和思路,感谢“程序员编辑部”博主 ( http://blog.csdn.net/programmer_editor/article/details/1898387 ) 和“andywxy”博主 ( http://blog.csdn.net/andywxy/article/details/1904151 )的详解,我用java重写了“程序员编辑部”博主的代码,又加了些我的理解注释,代码如下:】


Code:

import java.util.Scanner ;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner( System.in ) ;
		int N = sc.nextInt() ;
		String str = sc.next() ;
		char[] ch = str.toCharArray() ;
		int[] alpha = new int[26] ;	// 记录字母出现的次数
		// 判断是否可能被转成回文串
		for( int i = 0; i <N; i ++ ) {
			alpha[ ch[i] - 'a' ] ++ ;
		}
		char charodd = ' ';	// 记录可能的出现奇数次的字符
		int odd = 0 ;	// 统计alpha中有多少字母出现奇数次
		for( int i = 0; i < alpha.length; i ++ ) {
			if( alpha[i] % 2 != 0 ) {
				odd ++ ;
				charodd = (char) ('a' + i) ;	// 记录下出现奇数次的字符
			}
		}
		if( odd > 1 ) {		// 不可能转成回文串
			System.out.println( "Impossible" ) ;
		}
		else {
			int exchange = 0 ;	// 记录交换次数
			for( int i = 0; i < N/2; i ++ ) {		// 先看左边的字符
				if( ch[i] == charodd ) {	// 如果出现奇数次的字符在串的左边
					int j = 0 ;
					for( j = i; j <= N-i-1; j ++ ) {	// 从当前位置开始向后找与该位置的镜像位置相同的字母,例如: [ d, m, a, m, a, m, m ]    从j = 0向后找与ch[N-i-1] (即'm') 相同的字母
						if( ch[j] == ch[N-i-1] )	
							break ;
					}
					exchange += j-i ;	// 局部向后偏移的次数,即交换次数
					for( int k = j; k > i; k -- ) // 从当前位置开始到向后找到的第一个与 i 的镜像位置相同字母的位置处(包括该处)用前一个字符覆盖后一个字符	
						ch[k] = ch[k-1] ;
					ch[i] = ch[N-i-1] ;	// 之后用 i 的镜像位置的字符 填到 i 位置
				}
				else {	// 如果出现奇数次的字符不在串的左侧(或者不存在),则不用理他,因为当所有左侧字符都与右侧字符匹配好后,即使存在出现次数为奇数的字符,也会自动移动到中间位置
					int j = 0 ;
					for( j = N-i-1; j >= i; j -- ) {	// N-i-1是 i 在ch串中的镜像位置
						if( ch[j] == ch[i] )	// 从当前 i 的镜像位置向前找,找到第一个相同字符就退出(贪心策略),之所以不用向后找,因为后面的字符已经和前面的字符匹配好了
							break ;
					}
					exchange += N-i-1-j;	
					for( int k = j; k < N-i-1; k ++ ) 	// 从找到与 i 在串的镜像位置开始向前找到的第一个相同字母的位置起,到 i 的镜像位置(不包括镜像位置),用后一个字符覆盖前一个字符(即局部整体前移一位)
						ch[k] = ch[k+1] ;
					ch[N-i-1] = ch[i] ;	// 前移操作完后用 i 处的字符填到 i 的镜像位置处
				}
			}
			System.out.println( exchange );
		}
	}

}


今天做题明显感到了有一点难度,希望自己能继续坚持下去~~,在这过程中肯定少不了参考很多其他朋友的思路和代码,每次我参考其他博主的博文我都会附上链接,在此再次谢谢大家智慧的分享~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值