没有倒计时8,因为昨天有点事…真对不起自己
一、 翻硬币
思路:属于贪心算法, 从0开始比较,不相等就翻转,相等就继续
时间限制:1.0s 内存限制:256.0MB
问题描述
小明正在玩一个“翻硬币”的游戏。
桌上放着排成一排的若干硬币。我们用 * 表示正面,用 o 表示反面(是小写字母,不是零)。
比如,可能情形是:
**oo***oooo
如果同时翻转左边的两个硬币,则变为:
oooo***oooo
现在小明的问题是:如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币,那么对特定的局面,最少要翻动多少次呢?
我们约定:把翻动相邻的两个硬币叫做一步操作,那么要求:
输入格式
两行等长的字符串,分别表示初始状态和要达到的目标状态。每行的长度<1000
输出格式
一个整数,表示最小操作步数。
样例输入1
**********
o****o****
样例输出1
5
样例输入2
*o**o***o***
*o***o**o***
样例输出2
1
package lijie_3;
import java.util.Scanner;
/**
* 属于贪心算法
*
* 从0开始比较,不相等就翻转,相等就继续
* */
public class t_6 {
public static void main(String[] args) {
// String sa="*o**o***o***";
// String sb="*o***o**o***";
String sa="";
String sb="";
Scanner sc=new Scanner(System.in);
sa=sc.next();
sb=sc.next();
int step=0;
char []ca=sa.toCharArray();
char []cb=sb.toCharArray();
for(int i=0,j=0;i<ca.length-1&&j<cb.length-1;i++,j++){
if(ca[i]==cb[j]){
}else{
trans(ca,i);
step++;
}
}
System.out.println(step);
}
public static void trans(char []p,int i){
if(p[i]=='*'&&p[i+1]=='*'){
p[i]='o';
p[i+1]='o';
}else if(p[i]=='*'&&p[i+1]=='o'){
p[i]='o';
p[i+1]='*';
}else if(p[i]=='o'&&p[i+1]=='*'){
p[i]='*';
p[i+1]='o';
}else {
p[i]='*';
p[i+1]='*';
}
}
}
二、 连号区间数
题意(!!!我看了半天竟然没看懂题…):连续区间是指 在数组中,i位置与j位置内的,最小值与最大值的差等于j-i。
要求给出的任一数组,有多少个连续区间。
举例 [1,2,3]
位置 两个数 是否连续区间
0 0 1 1 0-0=1-1 是
0 1 1 2 1-0=2-1 是
0 2 1 3 2-0=3-1 是
。。。
举例子…举错了…这个例子真奇特…反正意思…应该可以明白了~
时间限制:1.0s 内存限制:256.0MB
问题描述
小明这些天一直在思考这样一个奇怪而有趣的问题:
在1~N的某个全排列中有多少个连号区间呢?这里所说的连号区间的定义是:
如果区间[L, R] 里的所有元素(即此排列的第L个到第R个元素)递增排序后能得到一个长度为R-L+1的“连续”数列,则称这个区间连号区间。
当N很小的时候,小明可以很快地算出答案,但是当N变大的时候,问题就不是那么简单了,现在小明需要你的帮助。
输入格式
第一行是一个正整数N (1 <= N <= 50000), 表示全排列的规模。
第二行是N个不同的数字Pi(1 <= Pi <= N), 表示这N个数字的某一全排列。
输出格式
输出一个整数,表示不同连号区间的数目。
样例输入1
4
3 2 4 1
样例输出1
7
样例输入2
5
3 4 2 5 1
样例输出2
9
package lijie_3;
import java.util.Scanner;
public class t_7 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int []num=new int[n];
for(int i=0;i<n;i++){
num[i]=sc.nextInt();
}
int res=0;
for(int i=0;i<n;i++){
int max=-1;
int min=5000;
for(int j=i;j<n;j++){
max=Math.max(num[j], max);
min=Math.min(num[j], min);
if((max-min)==(j-i)){
res++;
}
}
}
System.out.println(res);
}
}
三、 买不到的数目
思路:输入的是n m,一开始打算对于每一个数字:全是n可不可以;只有一个m可不可以;只有两个m可不可以。。。全是m可不可以。最后发现太费功夫。对于本题可以发现,如果一个数a可以用nm表示,那么a+n,a+m也可以用nm表示。那么就用数组来表示他们,如果一个数k能用nm来表示,就让num[k]=1。如果一个数p,p-m或p-n对应数组上的值为1,那p对应数组的值也是1,表示它也是可以被表示出来的~
时间限制:1.0s 内存限制:256.0MB
问题描述
小明开了一家糖果店。他别出心裁:把水果糖包成4颗一包和7颗一包的两种。糖果不能拆包卖。
小朋友来买糖的时候,他就用这两种包装来组合。当然有些糖果数目是无法组合出来的,比如要买 10 颗糖。
你可以用计算机测试一下,在这种包装情况下,最大不能买到的数量是17。大于17的任何数字都可以用4和7组合出来。
本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。
输入格式
两个正整数,表示每种包装中糖的颗数(都不多于1000)
输出格式
一个正整数,表示最大不能买到的糖数
样例输入1
4 7
样例输出1
17
样例输入2
3 5
样例输出2
7
package lijie_3;
import java.util.Scanner;
public class t_8 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int m=sc.nextInt();
dt(n,m);
}
public static void dt(int n,int m){
int []num=new int[100001];
int []a=new int[2];
a[0]=n;a[1]=m;
num[a[0]]=1;
num[a[1]]=1;
int max=0;
for(int i=1;i<100001;i++){
int flag=0;
for(int j=0;j<2;j++){
if(i-a[j]>0&&num[i-a[j]]==1){
num[i]=1;
flag=1;
}
}
if(flag==0){
max=i;
}
}
System.out.println(max);
}
}
四、大臣的旅费 (运行超时)
满分答案在这里
我的具体操作…就是分别以i为开始,深度优先的查询最长长度,所以超时了…
舞动的心 这个作者,直接以1开始走dfs,就能直接找出来最长的那个节点…我没看懂…
这个作者的存储方式…也让我受益匪浅~:
ArrayList<edge>[] map是这种样子的:
null
[1,2,2, 1,3,1]
[2,1,2, 2,4,5, 2,5,4]
[3,1,1]
[4,2,5]
[5,2,4]
时间限制:1.0s 内存限制:256.0MB
问题描述
很久以前,T王国空前繁荣。为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。
为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。
J是T国重要大臣,他巡查于各大城市之间,体察民情。所以,从一个城市马不停蹄地到另一个城市成了J最常做的事情。他有一个钱袋,用于存放往来城市间的路费。
聪明的J发现,如果不在某个城市停下来修整,在连续行进过程中,他所花的路费与他已走过的距离有关,在走第x千米到第x+1千米这一千米中(x是整数),他花费的路费是x+10这么多。也就是说走1千米花费11,走2千米要花费23。
J大臣想知道:他从某一个城市出发,中间不休息,到达另一个城市,所有可能花费的路费中最多是多少呢?
输入格式
输入的第一行包含一个整数n,表示包括首都在内的T王国的城市数
城市从1开始依次编号,1号城市为首都。
接下来n-1行,描述T国的高速路(T国的高速路一定是n-1条)
每行三个整数Pi, Qi, Di,表示城市Pi和城市Qi之间有一条高速路,长度为Di千米。
输出格式
输出一个整数,表示大臣J最多花费的路费是多少。
样例输入1
5
1 2 2
1 3 1
2 4 5
2 5 4
样例输出1
135
输出格式
大臣J从城市4到城市5要花费135的路费。
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static int n;
public static int Max = Integer.MIN_VALUE;
public static int point = 0;
public static ArrayList<edge>[] map;
static class edge {
public int P;
public int Q;
public int D;
public edge(int P, int Q, int D) {
this.P = P;
this.Q = Q;
this.D = D;
}
public String toString(){
return this.P+","+this.Q+","+this.D;
}
}
public void dfs(int start, boolean[] visited, int dis) {
visited[start] = true;
for(int i = 0;i < map[start].size();i++) {
edge temp = map[start].get(i);
if(visited[temp.Q] == false) {
dis += temp.D;
if(dis > Max) {
Max = dis;
point = temp.Q;
}
dfs(temp.Q, visited, dis);
dis -= temp.D;
}
}
}
public void getResult() {
boolean[] visited = new boolean[n + 1];
int m=0;
for(int i=1;i<map.length;i++){
dfs(i, visited, 0);
visited = new boolean[n + 1];
m=Math.max(Max,m);
}
int result = m * 10 + (m + 1) * m / 2;
System.out.println(result);
}
public static void main(String[] args) {
Main test = new Main();
Scanner in = new Scanner(System.in);
n = in.nextInt();
map = new ArrayList[n + 1];
for(int i = 1;i <= n;i++)
map[i] = new ArrayList<edge>();
for(int i = 1;i < n;i++) {
int P = in.nextInt();
int Q = in.nextInt();
int D = in.nextInt();
map[P].add(new edge(P, Q, D));
map[Q].add(new edge(Q, P, D));
}
// for(int i=0;i<n+1;i++){
// System.out.println(map[i]);
// }
test.getResult();
}
}
五、幸运数
有个坑…注意2和别的幸运数不一样…
时间限制:1.0s 内存限制:256.0MB
问题描述
幸运数是波兰数学家乌拉姆命名的。它采用与生成素数类似的“筛法”生成
。
首先从1开始写出自然数1,2,3,4,5,6,…
1 就是第一个幸运数。
我们从2这个数开始。把所有序号能被2整除的项删除,变为:
1 _ 3 _ 5 _ 7 _ 9 …
把它们缩紧,重新记序,为:
1 3 5 7 9 … 。这时,3为第2个幸运数,然后把所有能被3整除的序号位置的数删去。注意,是序号位置,不是那个数本身能否被3整除!! 删除的应该是5,11, 17, …
此时7为第3个幸运数,然后再删去序号位置能被7整除的(19,39,…)
最后剩下的序列类似:
1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, …
输入格式
输入两个正整数m n, 用空格分开 (m < n < 1000*1000)
输出格式
程序输出 位于m和n之间的幸运数的个数(不包含m和n)。
样例输入1
1 20
样例输出1
5
样例输入2
30 69
样例输出2
8
package lijie_3;
import java.util.LinkedList;
import java.util.Scanner;
public class t_10{
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
int m = reader.nextInt();
int n = reader.nextInt();
LinkedList<Integer> list = new LinkedList<Integer>();
for (int i = 1; i < n; i = i + 2) {
list.add(i);
}
int order = 1;
int num;
while (order < list.size()) {
num = (int) list.get(order);//取出幸运数
int step = 0;
int size = list.size();//固定大小
for (int i = 0; i < size; i++) {
if ((i + 1) % num == 0) {
list.remove(i - step);//去掉下标可以整除幸运数的值
step++;//当前链表删除掉的数量
}
}
order++;//下一个幸运数的位置
}
//计数
int count=0;
while(!list.isEmpty())
{
int temp=(int) list.pop();
if(temp<n&&m<temp)
{
count++;
}
}
System.out.println(count);
}
}