2的次幂表示
前缀表达式
Anagrams问题
出现次数最多的整数
大小写转换
最大的算式
区间k大数查询
未名湖边的烦恼
最大最小公倍数
K好数
数字三角形
寻找数组中最大值
5-1最小公倍数
关联矩阵
结点选择
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n;
while(in.hasNext()){
n= in.nextInt();
System.out.println(f(n));
}
}
public static String f(int n) {
String a;
if(n == 0){
return "2(0)";
}else if(n == 1){
return "2";
}else if(n == 2){
return "2(2)";
}else {
a = Integer.toBinaryString(n);
int len = a.length();
String result = "";
for(int i = 0; i < len; i++){
if(a.charAt(i) == '1') {
if(len-i-1 >2) {
if(result == ""){
result = result + "2(" +f(len-i-1) +")";
}else{
result = result + "+2("+f(len-i-1)+")";
}
}else if(len-i-1 <=2){
if(result == ""){
result = f(len-i-1);
}else {
result = result + "+" + f(len-i-1);
}
}
}
}
return result;
}
}
}
import java.util.Scanner;
public class Main1 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String n;
while(in.hasNext()){
n= in.nextLine();
String[] str =n.split(" ");
int num1 = Integer.parseInt(str[1]);
int num2 = Integer.parseInt(str[2]);
switch(str[0]) {
case "+":
System.out.println(add(num1,num2));
break;
case "-":
System.out.println(sub(num1,num2));
break;
case "*":
System.out.println(mul(num1,num2));
break;
case "/":
System.out.println(div(num1,num2));
break;
}
}
}
public static int add(int a, int b){
return a + b;
}
public static int sub(int a, int b){
return a - b;
}
public static int mul(int a, int b){
return a * b;
}
public static int div(int a, int b){
return a / b;
}
}
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while(in.hasNext()){
int arr1[] = new int[26];
int arr2[] = new int[26];
for(int i = 0; i < 26; i++){
arr1[i] = 0;
arr2[i] = 0;
}
String str1 = in.next().toLowerCase();
String str2 = in.next().toLowerCase();
int len1= str1.length();
int len2 = str2.length();
for(int i = 0; i < len1; i++){
arr1[str1.charAt(i)- 'a'] += 1;
}
for(int i = 0; i < len2; i++){
arr2[str2.charAt(i)- 'a'] += 1;
}
boolean check = false;
for(int i = 0; i < 26; i++) {
if(arr1[i] != arr2[i]) {
check = true;
break;
}
}
if(check){
System.out.println("N");
}else{
System.out.println("Y");
}
}
}
}
import java.util.Scanner;
//这代码只能得80分,不知道哪里错了
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while(in.hasNext()){
int n = in.nextInt();
int arr[] = new int[n]; //存储输入数据
int index[] = new int[n]; //记录次数
int max = 0; //标记最大的位置
int temp;
for(int i = 0; i < n; i++) {
index[i] = 0;
}
int p = 0;
arr[p] = in.nextInt();
index[p] +=1;
max = p;
p++;
for(int i = 1; i < n; i++) {
temp = in.nextInt();
if(temp == arr[p-1]) {
index[p-1] += 1;
if(index[p-1] > index[max]){
max = p-1;
}
}else{
arr[p] = temp;
index[p] += 1;
if(index[p] > index[max]){
max = p;
}
p++;
}
}
System.out.println(arr[max]);
}
}
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while(in.hasNext()){
String str = in.next();
int len = str.length();
char arr[] = new char[len];
for(int i = 0; i < len; i++) {
arr[i] = str.charAt(i);
if(arr[i] >= 'A' && arr[i] <= 'Z') {
arr[i] = (char) (arr[i] + 32);
}else {
arr[i] =(char)(arr[i] - 32);
}
}
System.out.println(new String(arr));
}
}
}
思路:提示说按照dp处理,就往这边想了,先确定了dp[i][j]表示前i个数中使用了j个乘号的所得到最大值。
纠结于插入的位置,所以只好再设一重循环,表示可以插入的位置,范围从2到n。
动态转移方程是根据01背包的思想转化得来的,选定插入位置,前面的最大值乘后边从插入位置到i之前的总和,原来想的是只乘一个数,但是一起乘总比一个去乘要大。
所以状态转移方程:dp[i][j]=max(dp[i][j],dp[p-1][j-1]*(p到i之间的总和));
最后就是初始状态的考虑,dp[i][0]表示没有用到乘号,所以dop[i][0]就是前i项的和。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while(in.hasNext()) {
int n = in.nextInt();
int m = in.nextInt();
Long arr[] = new Long[16];
Long dp[][] = new Long[16][16];
for(int i = 0; i < 16; i++) {
for(int j = 0; j < 16; j++) {
dp[i][j] = 0L;
}
}
arr[0] = 0L;
for(int i = 1; i <= n; i++) {
arr[i] = in.nextLong();
dp[i][0] = dp[i-1][0] + arr[i]; //在没有使用乘号的情况全部使用加法
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= i - 1; j++) {
for(int p = 2; p <= i; p++) { //第j个乘号插入的位置,如果和前面的乘号位置重叠了,也不影响,还是原来的dp[i][j]
dp[i][j] = Math.max(dp[i][j], dp[p-1][j-1] * (dp[i][0] - dp[p-1][0])); //从车如位置到i的和,一起乘总比一个乘要大
}
}
}
System.out.println(dp[n][m]);
}
}
}
给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个。
第一行包含一个数n,表示序列长度。
第二行包含n个正整数,表示给定的序列。
第三个包含一个正整数m,表示询问个数。
接下来m行,每行三个数l,r,K,表示询问序列从左往右第l个数到第r个数中,从大往小第K大的数是哪个。序列元素从1开始标号。
对于30%的数据,n,m<=100;
对于100%的数据,n,m<=1000;
保证k<=(r-l+1),序列中的数<=106。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while(in.hasNext()) {
int n = in.nextInt();
Integer arr[] = new Integer[n+1];
int l = 0,c = 0,r = 0;
PriorityQueue pq = null; //排序队列
arr[0] = 1;
for(int i = 1; i <= n; i++) {
arr[i] = in.nextInt();
}
int m = in.nextInt();
for(int i = 0; i < m; i++) {
l = in.nextInt();
c = in.nextInt();
r = in.nextInt();
pq = new PriorityQueue();
for(int j = l; j <= c ; j++){
pq.add(arr[j]); //添加自动实现排序(从小到大)
}
int len = pq.size() - r;
for(int k = 1; k <= len; k++){
pq.poll(); //弹出队头并删除
}
System.out.println(pq.peek()); //弹出队头不删除
}
}
}
}
递归法
共有m个人还鞋,n个人借鞋,记最终排列数为f(m, n)。
现在求m和n的排队情况,具体理解如下:
起始,要去一人还鞋(PS:此时,m = m - 1),还完后,可以选一人还鞋(PS:m = m - 1)或者一人借鞋(PS:n = n - 1)。
那么,f(m , n) = f(m - 1, n) + f(m, n - 1)。这就是求取f(m, n)的递推公式,那么轻易可知当m < n时,f(m, n) = 0;当n = 0时,f(m, 0) = 1。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int m = in.nextInt();
int n = in.nextInt();
System.out.println(fun(m,n));
}
public static int fun(int m, int n) {
//System.out.println("fun("+ (m-1) + "," + n +")+fun(" + m + "," + (n-1) + ");");
if(m < n){
return 0;
}
if(n == 0) {
return 1;
}
return fun(m-1,n) + fun(m, n-1);
}
}
递推法
import java.util.Scanner;
public class Main{
//m代表还鞋的人数,n代表借鞋的人数
public int getArrange1(int m, int n) {
int[][] result = new int[m + 1][n + 1]; //初始化元素全为0
for(int i = 1;i <= m;i++) {
result[i][0] = 1; //当借鞋的人数为0时,排列只有一种情况
for(int j = 1;j <= n;j++) {
if(i >= j) //当i小于j时,排列总数为0
result[i][j] = result[i - 1][j] + result[i][j - 1];
}
}
return result[m][n];
}
public static void main(String[] args){
Main test = new Main();
Scanner in = new Scanner(System.in);
// System.out.println("请分别输入还鞋人数m和和借鞋人数n:");
int m = in.nextInt();
int n = in.nextInt();
System.out.println(test.getArrange1(m, n));
}
}
已知一个正整数N,问从1~N中任选出三个数,他们的最小公倍数最大可以为多少。
输入一个正整数N。
1 <= N <= 106。
题意分析:在n个数中找任意三个数的最小公倍数,并且求得最大的最小公倍数(重点在于最大)。
思路分析:最大 最小公倍数,联想到两个数的求最大最小公倍数,即两个数的乘积(注:连续的两个自然数是互斥的)。
同样,我们可以拿最后三个数来做考虑。
1.当n为奇数时,n,n-1,n-2为奇偶奇,里面只有一个偶数,所以不会有2这个因子。这三个数相差不到3,所以也不会有因子3,故符合题意。
2.当n为偶数时,n,n-1,n-2为偶奇偶,此时n,n-2肯定含有因子2,所以除于2不值得。所以考虑将n-2 换成n-3,变成奇偶奇,此时也有一个问题,
n和n-3,如果n%3==0,则除于3更不值得。仍根据奇偶奇的原则,变动偶数n为n-2,此时换成n-1,n-2,n-3和1情况一样。故此时符合题意。
粗心:忘记了结果的long处理,数据处理超过了int的大小。import java.math.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws Exception {
Scanner in = new Scanner(System.in);
while(in.hasNext()) {
long n = in.nextLong();
long sum;
if(n%2 == 1) {
System.out.println(n*(n-1)*(n-2));
}else {
if(n%3 == 0) {
System.out.println((n-1)*(n-2)*(n-3));
}else {
sum = n*(n-1)*(n-3);
System.out.println(sum);
}
}
}
}
}
如果一个自然数N的K进制表示中任意的相邻的两位都不是相邻的数字,那么我们就说这个数是K好数。求L位K进制数中K好数的数目。例如K = 4,L = 2的时候,所有K好数为11、13、20、22、30、31、33 共7个。由于这个数目很大,请你输出它对1000000007取模后的值。
输入包含两个正整数,K和L。
对于30%的数据,KL <= 106;
对于50%的数据,K <= 16, L <= 10;
对于100%的数据,1 <= K,L <= 100。
典型的动态规划题:一位一位的去填充,用一个二维数组arr[i][j]表示i位数以j结尾一共有多少种,接下来要放下一位的话,只要判断要放的这位数字是否是j的邻位即可。
dp[i][j],其中 i 表示总共有多少位(i<=L),j 表示最后面那个数字(j 普通的dp问题,自底向上求最大就可以了 样例输出 对于有向图,若bij = 1,表示边j离开点i。 若bij = -1, 表示边j进入点i。 若bij = 0,表示边j和点i不相关联。 很明显题意是有向图 有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少? 第一行包含一个整数 n 。 接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。 接下来一共 n-1 行,每行描述树上的一条边。 对于20%的数据, n <= 20。 对于50%的数据, n <= 1000。 对于100%的数据, n <= 100000。 权值均为不超过1000的正整数。 百度找的题解,能力不足,还是看不懂,先扑上去,有时间再看看。 看过这道题,我们大概可以知道,这是一道和树有关的问题,那么我们需要考虑的就是如何去遍历树?很明显,我们需要用到DFS。仔细读这道题,然后我们就可以得到这还需要用到动态规划,由此,我们做这道题,解题方案也就是树形动态规划了! 既然要用动态规划,构造状态转移方程是必不可少了! 代码如下:
总共1位: 全部初始化为1,方便arr[2][j] 规划。
总共2位:...... (还是直接看下面的数组吧)。
当输入:>> 4 2 时,如下:(行i
所以:7 = 2 + 2 + 3
0
1
2
3
1
1
1
1
1
2
3
2
2
3
import java.math.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws Exception {
Scanner in = new Scanner(System.in);
while(in.hasNext()) {
int k = in.nextInt();
int L = in.nextInt();
long sum = 0;
long arr[][] = new long[505][105];
for(int i = 0; i < k; i++) { //如果是一位数,那么每个小于k的数就是1
arr[1][i] = 1;
}
for(int i = 2; i <= L; i++) {
for(int j = 0; j < k; j++) {
for(int x = 0; x < k; x++) {
if(x != j-1 && x != j+1) { //左右不相邻
arr[i][j] += arr[i-1][x];
arr[i][j] %= 1000000007;
}
}
}
}
for (int i = 1; i < k; i++) { //将最后一行累加,第一列0,不统计
sum += arr[L][i];
sum %= 1000000007;
}
System.out.println(sum);
}
}
}
径,使该路径所经过的数字的总和最大。
●每一步可沿左斜线向下或右斜线向下走;
●1<三角形行数≤100;
●三角形中的数字为整数0,1,…99;
.
(图3.1-1)
接下来描述整个三角形
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
code:import java.math.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws Exception {
Scanner in = new Scanner(System.in);
int dp[][] = new int[101][101];
while(in.hasNext()) {
int n = in.nextInt();
for(int i = 1; i <= n;i++) {
for(int j = 1; j <= i; j++) {
dp[i][j] = in.nextInt();
}
}
int max = 0;
int temp;
for(int i = n - 1; i >= 1; i--) {
for(int j = 1; j <= i; j++) {
temp = Math.max(dp[i+1][j],dp[i+1][j+1]);
dp[i][j] += temp;
if(dp[i][j] > max) {
max = dp[i][j];
}
}
}
System.out.println(max);
}
}
}
3
3 2 1
3 0
import java.math.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws Exception {
Scanner in = new Scanner(System.in);
while(in.hasNext()) {
int n = in.nextInt();
int max = 0;
int index = 0;
int number;
for(int i= 0; i < n; i++ ) {
number = in.nextInt();
if(number > max) {
max = number;
index = i;
}
}
System.out.println(max + " " + index);
}
}
}
例:
3 5
例:
例:两个数都小于65536。
import java.math.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws Exception {
Scanner in = new Scanner(System.in);
while(in.hasNext()) {
int n = in.nextInt();
int m = in.nextInt();
System.out.println(n*m/dp(n, m));
}
}
public static int dp(int a, int b) {
return b == 0? a: dp(b, a%b);
}
}
接下来m行,每行两个整数a、b,表示图中有(a,b)边。
注意图中可能含有重边,但不会有自环。
1 2
3 1
1 5
2 5
2 3
2 3
3 2
4 3
5 4
-1 0 0 1 1 1 -1 0 0
0 1 0 0 -1 -1 1 -1 0
0 0 0 0 0 0 0 1 -1
0 0 -1 -1 0 0 0 0 1
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n, m,a,b;
int arr[][] = new int[105][1005];
while(in.hasNext()) {
n = in.nextInt();
m = in.nextInt();
for(int i = 1; i <= m; i++) {
a = in.nextInt();
b = in.nextInt();
arr[a][i] = 1;
arr[b][i] = -1;
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++){
System.out.print(arr[i][j]);
if(j != m) {
System.out.print(" ");
}else {
System.out.println();
}
}
}
}
}
}
1 2 3 4 5
1 2
1 3
2 4
2 5
对于叶子结点:
dp[k][0] = 0;
dp[k][1] = k点权值;
对于非叶子结点:
dp[i][0] = max(dp[j][0], dp[j][1]); (j是i的儿子)
dp[i][1] = i点权值 + dp[j][0]; (j是i的儿子)
最大权值即为:
max(dp[0][0], dp[0][1])。(要么不包括根结点,要么包括根结点)
#include