倒计时2

写在开头…由于测试点问题,在本地eclipse上运行无错。但可能由于个人粗心,导致出现边界错误,或者思路错误。但是在官网和学校的训练网站上并没有搭建17、18年题目的环境,所以我也无法保证我写的完全是正确的,个人保证最大程度的正确。如果出现错误,欢迎指教,谢谢~
一、标题:日期问题

小明正在整理一批历史文献。这些历史文献中出现了很多日期。小明知道这些日期都在1960年1月1日至2059年12月31日。令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的。更加麻烦的是,年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。

比如02/03/04,可能是2002年03月04日、2004年02月03日或2004年03月02日。

给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?

输入
一个日期,格式是"AA/BB/CC"。 (0 <= A, B, C <= 9)

输入
输出若干个不相同的日期,每个日期一行,格式是"yyyy-MM-dd"。多个日期按从早到晚排列。

样例输入
02/03/04

样例输出
2002-03-04
2004-02-03
2004-03-02

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms

思路:全排列+合理的时间

package lijie_17;

import java.util.Scanner;

public class s_7 {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		String s=sc.next();
		String []ss=s.split("/");
//		for(int i=0;i<=2;i++){
//			System.out.print(ss[i]+" ");
//		}
//		System.out.println();
//		String []num={"98","02","08"};
		demo(ss, 0, 2);
	}
	public static void format(String[] num){
		int []nums=new int [3];
		nums[0]=Integer.valueOf(num[0]);
		nums[1]=Integer.valueOf(num[1]);
		nums[2]=Integer.valueOf(num[2]);
//		for(int i=0;i<=2;i++){
//			System.out.print(nums[i]+" ");
//		}
//		System.out.println();
		if(nums[1]==1||nums[1]==3||nums[1]==5||nums[1]==7||nums[1]==8||nums[1]==10||nums[1]==11){
			if(nums[2]<=31){
				if(nums[0]>=60){
					nums[0]+=1900;
				}else{
					nums[0]+=2000;
				}
				String m="";
				if(nums[1]>=10){
					m=String.valueOf(nums[1]);
				}else{
					m="0"+nums[1];
				}
				String d="";
				if(nums[2]>=10){
					d=String.valueOf(nums[2]);
				}else{
					d="0"+nums[2];
				}
				String s=String.valueOf(nums[0])+"-"+m+"-"+d;
				System.out.println(s);
			}
		}else{
			if(nums[2]<=30){
				if(nums[0]>=60){
					nums[0]+=1900;
				}else{
					nums[0]+=2000;
				}
				String m="";
				if(nums[1]>=10){
					m=String.valueOf(nums[1]);
				}else{
					m="0"+nums[1];
				}
				String d="";
				if(nums[2]>=10){
					d=String.valueOf(nums[2]);
				}else{
					d="0"+nums[2];
				}
				String s=String.valueOf(nums[0])+"-"+m+"-"+d;
				System.out.println(s);
			}
		}
		
	}
	public static void demo(String []num,int start,int end){
		if(start==end){
//			for(int i=0;i<=end;i++){
//				System.out.print(num[i]+" ");
//			}
//			System.out.println();
			if(Integer.parseInt(num[1])>0&&Integer.parseInt(num[1])<13&&Integer.parseInt(num[2])>0&&Integer.parseInt(num[2])<32){
				//闰年
				if(Integer.parseInt(num[0])%400==0||(Integer.parseInt(num[0])%4==0&&Integer.parseInt(num[0])%100!=0)){
					if(Integer.parseInt(num[1])==2&&Integer.parseInt(num[2])<=29){
						format(num);
					}else if(Integer.parseInt(num[1])!=2){
						format(num);
					}
				}else{
					if(Integer.parseInt(num[1])==2&&Integer.parseInt(num[2])<=28){
						format(num);
					}else if(Integer.parseInt(num[1])!=2){
						format(num);
					}
				}
			}
		}
		for(int i=start;i<=end;i++){
			swap(num, i, start);
			demo(num, start+1, end);
			swap(num, i, start);
		}
	}
	public static void swap(String []num,int i,int j){
		String t=num[i];
		num[i]=num[j];
		num[j]=t;
	}
}

二、标题:包子凑数

小明几乎每天早晨都会在一家包子铺吃早餐。他发现这家包子铺有N种蒸笼,其中第i种蒸笼恰好能放Ai个包子。每种蒸笼都有非常多笼,可以认为是无限笼。

每当有顾客想买X个包子,卖包子的大叔就会迅速选出若干笼包子来,使得这若干笼中恰好一共有X个包子。比如一共有3种蒸笼,分别能放3、4和5个包子。当顾客想买11个包子时,大叔就会选2笼3个的再加1笼5个的(也可能选出1笼3个的再加2笼4个的)。

当然有时包子大叔无论如何也凑不出顾客想买的数量。比如一共有3种蒸笼,分别能放4、5和6个包子。而顾客想买7个包子时,大叔就凑不出来了。

小明想知道一共有多少种数目是包子大叔凑不出来的。

输入
第一行包含一个整数N。(1 <= N <= 100)
以下N行每行包含一个整数Ai。(1 <= Ai <= 100)

输出
一个整数代表答案。如果凑不出的数目有无限多个,输出INF。

例如,
输入:
2
4
5

程序应该输出:
6

再例如,
输入:
2
4
6

程序应该输出:
INF

样例解释:
对于样例1,凑不出的数目包括:1, 2, 3, 6, 7, 11。
对于样例2,所有奇数都凑不出来,所以有无限多个。

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms

思路: 感觉是历届 题目 买不到的数目的升级版。多了一个INF,如果数的最大公约数不是1,那就是INF,因为数之间存在间隔了

package lijie_17;

import java.util.Arrays;
import java.util.Scanner;

public class s_8 {
	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();
		}
		if(zdgy(num)){
			demo(num);
		}else{
			System.out.println("INF");
		}
	}
	/**
	 * 判断最大公约数是不是1
	 * */
	public static boolean zdgy(int []num){
		Arrays.sort(num);
		int a=num[0];
		for(int i=2;i<=a;i++){
			int flag=0;
			for(int j=0;j<num.length;j++){
				if(num[j]%i==0){
					flag++;
				}
			}
			if(flag==num.length){
				return false;
			}
		}
		return true;
	}
	
	public static void demo(int []num){
		Arrays.sort(num);
		int []a=new int[100001];
		for(int i=0;i<num.length;i++){
			a[num[i]]=1;
		}
		int res=0;
		for(int i=1;i<100001;i++){
			int flag=0;
			for(int j=0;j<num.length;j++){
				if(a[i]!=1){
					if(i-num[j]>0&&a[i-num[j]]==1){
						a[i]=1;
						flag=1;
					}
				}else{
					flag=1;
				}
			}
			if(flag==0){
				res++;
//				System.out.println(i);
			}
		}
		System.out.println(res);
		
	}
	
}

三、标题: 分巧克力

儿童节那天有K位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。小明一共有N块巧克力,其中第i块是Hi x Wi的方格组成的长方形。为了公平起见,小明需要从这 N 块巧克力中切出K块巧克力分给小朋友们。切出的巧克力需要满足:

  1. 形状是正方形,边长是整数
  2. 大小相同

例如一块6x5的巧克力可以切出6块2x2的巧克力或者2块3x3的巧克力。

当然小朋友们都希望得到的巧克力尽可能大,你能帮小Hi计算出最大的边长是多少么?

输入
第一行包含两个整数N和K。(1 <= N, K <= 100000)
以下N行每行包含两个整数Hi和Wi。(1 <= Hi, Wi <= 100000)
输入保证每位小朋友至少能获得一块1x1的巧克力。

输出
输出切出的正方形巧克力最大可能的边长。

样例输入:
2 10
6 5
5 6

样例输出:
2

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms

思路:模拟切的过程,j从1开始,到最短的边长结束。如果宽大于j,那就j行j行的切,如果小于j,那就结束。

import java.util.Scanner;

public class s_9 {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int m=sc.nextInt();
		int [][]num=new int[n][2];
		int min=100002;
		for(int i=0;i<n;i++){
			int a=sc.nextInt();
			int b=sc.nextInt();
			if(a<=b){
				num[i][0]=a;
				num[i][1]=b;
				min=Math.min(a, min);
			}else{
				num[i][0]=b;
				num[i][1]=a;
				min=Math.min(b, min);
			}
		}
		int res=-1;
		for(int i=1;i<min;i++){
			int kuai=0;
			for(int j=0;j<n;j++){
				int t=num[j][0];
				int tt=num[j][1];
				while(t>=i){
					kuai+=tt/i;
					t-=i;	
				}
			}
			if(kuai>=m){
				res=Math.max(i, res);
//				System.out.println(i+" "+kuai);
			}
		}
		System.out.println(res);
	}
}

四、标题:复数幂
设i为虚数单位。对于任意正整数n,(2+3i)^n 的实部和虚部都是整数。
求 (2+3i)^123456 等于多少? 即(2+3i)的123456次幂,这个数字很大,要求精确表示。
答案写成 “实部±虚部i” 的形式,实部和虚部都是整数(不能用科学计数法表示),中间任何地方都不加空格,实部为正时前面不加正号。(2+3i)^2 写成: -5+12i,
(2+3i)^5 的写成: 122-597i

思路:(2+3i)的n次方都可以记作(a+bi)(2+3i),不同的只是a+bi中的a和b。从2次方开始模拟,就可以得到最终答案13483137+1100011648i
我当时担心的问题还有 是否存在4个一循环,毕竟i的4次方才为1。分别拿(2+3i)的2次方3次方进行计算,发现不存在这个问题,是符合(a+bi)(2+3i)的。

我更新~在我哥的指点下,发现用long会变化,那就证明int是不可以的…思路大概这样…但是要用BigInteger

package lijie_18;

public class s_3 {
	public static void main(String[] args) {
		int a=2;
		int b=3;
		int n=123456;
		int ta,tb;
		for(int i=2;i<=n;i++){
			ta=2*a-3*b;
			tb=3*a+2*b;
			a=ta;
			b=tb;
		}
		if(b>=0){
			System.out.println(a+"+"+b+"i");
		}else{
			System.out.println(a+""+b+"i");
		}
	}
}

五、标题:快速排序

以下代码可以从数组a[]中找出第k小的元素。
它使用了类似快速排序中的分治算法,期望时间复杂度是O(N)的。
请仔细阅读分析源码,填写划线部分缺失的内容。

import java.util.Random;
public class Main{
	public static int quickSelect(int a[], int l, int r, int k) {
		Random rand = new Random();
		int p = rand.nextInt(r - l + 1) + l;
		int x = a[p];
		int tmp = a[p]; a[p] = a[r]; a[r] = tmp;
		int i = l, j = r;
		while(i < j) {
                	while(i < j && a[i] < x) i++;
                	if(i < j) {
                        	a[j] = a[i];
                        	j--;
                	}
                	while(i < j && a[j] > x) j--;
                	if(i < j) {
                        	a[i] = a[j];
                        	i++;
                	}
        	}
        	a[i] = x;
        	p = i;
        	if(i - l + 1 == k) return a[i];
        	if(i - l + 1 < k) return quickSelect( _________________________________ ); //填空
        	else return quickSelect(a, l, i - 1, k);	
	}
	public static void main(String args[]) {
		int [] a = {1, 4, 2, 8, 5, 7};
		System.out.println(quickSelect(a, 0, 5, 4));
	}
}

答案:return quickSelect(a,i+1,r,k-i+l-1);
思路:能看出来是随机选择一个数,将比这个数小的放在左边,比这个数大的放在右边。如果这个数在第k位,那就是我们要求的数。如果比k大,就在k的右边找。问题是,在比k小,在左边找的时候的循环函数。四个空,可以确定两个,a和r。剩下的两个是左边界和第几小。挨个试吧…
六、标题:递增三元组

给定三个整数数组
A = [A1, A2, … AN],
B = [B1, B2, … BN],
C = [C1, C2, … CN],
请你统计有多少个三元组(i, j, k) 满足:

  1. 1 <= i, j, k <= N
  2. Ai < Bj < Ck

【输入格式】
第一行包含一个整数N。
第二行包含N个整数A1, A2, … AN。
第三行包含N个整数B1, B2, … BN。
第四行包含N个整数C1, C2, … CN。

对于30%的数据,1 <= N <= 100
对于60%的数据,1 <= N <= 1000
对于100%的数据,1 <= N <= 100000 0 <= Ai, Bi, Ci <= 100000

【输出格式】
一个整数表示答案

【输入样例】
3
1 1 1
2 2 2
3 3 3

【输出样例】
27

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms

思路: a[i]代表a中i出现的次数,b[i]代表b中i出现次数。c同理。ai<bj<ck
那就统计a[]中比ai小的有多少个。举例吧…
1 1 1 —a[]
2 2 2 —b[]
3 3 3—c[]

初始时,a[1]=3,b[2]=3,c[3]=3。对于b来说,比2小的是1,那就对应a[1]=3,所以b[2]*=a[1],b[2]=9,代表以b的2结尾有9种可能性(题目隐含可以包含重复的)。同理,c[3]*=b[2],即27
但是范围扩大,如果是
1 2 3
2 5 6
5 7 8
这种,那么a[1]=1,a[2]=1,a[3]=1.b[2]=1,b[5]=1,b[6]=1,c[5]=1,c[7]=1,c[8]=1
如果选择以b中6结尾,那么a中的三个都可以选择,可以表示成a[2]=1,a[3]=2,a[5]=3;代表着着在选择a[i]的时候可以有多少种可能性。将b[]也进行上述变化。可得代码
package lijie_18;

import java.util.Scanner;

public class s_6 {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int []a=new int[100001];
		for(int i=0;i<n;i++){
			a[sc.nextInt()]++;
		}
		int []b=new int[100001];
		for(int i=0;i<n;i++){
			b[sc.nextInt()]++;
		}
		int []c=new int[100001];
		for(int i=0;i<n;i++){
			c[sc.nextInt()]++;
		}
		
		for(int i=1;i<100001;i++){
			a[i]+=a[i-1];
//			System.out.print(a[i]+"!!!");
		}
		for(int i=1;i<100001;i++){
			b[i]*=a[i-1];
				b[i]+=b[i-1];
//			System.out.print(b[i]+"*");
		}
//		System.out.println();
		int res=0;
		for(int i=1;i<100001;i++){
			c[i]*=b[i-1];
			res+=c[i];
//			System.out.print(c[i]+"@");
			
		}
//		System.out.println();
		System.out.println(res);
		
	}
}

七、标题:螺旋折线

如图p1.pgn所示的螺旋折线经过平面上所有整点恰好一次。
对于整点(X, Y),我们定义它到原点的距离dis(X, Y)是从原点到(X, Y)的螺旋折线段的长度。

例如dis(0, 1)=3, dis(-2, -1)=9

给出整点坐标(X, Y),你能计算出dis(X, Y)吗?

【输入格式】
X和Y

对于40%的数据,-1000 <= X, Y <= 1000
对于70%的数据,-100000 <= X, Y <= 100000
对于100%的数据, -1000000000 <= X, Y <= 1000000000

【输出格式】
输出dis(X, Y)

【输入样例】
0 1

【输出样例】
3

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。
主类的名字必须是:Main,否则按无效代码处理。

思路:找到每半圈cir的长度相等,和下半圈x,y方向相反,模仿螺旋线的轨迹,运用while循环

package lijie_18;

public class s_7 {
	public static void main(String[] args) {
		int x=0,y=0;//初始点
		int resx=2,resy=0;//目标点
		int dirx=-1,diry=1;//方向
		int res=0;//步数
		int cir=1;//每一圈步数
		while(true){
			int tcir=cir;
			if(x==resx&&y==resy){
				System.out.println(res);
				break;
			}
			int flag=0;
			while(cir-->0){
				x+=dirx;
				res++;
				if(x==resx&&y==resy){
					System.out.println(res);
					flag=1;
					break;
				}
			}
			if(flag==1){
				break;
			}
			cir=tcir;
			while(cir-->0){
				y+=diry;
				res++;
				if(x==resx&&y==resy){
					System.out.println(res);
					flag=1;
					break;
				}
			}
			if(flag==1){
				break;
			}
			cir=tcir;
			cir++;
			dirx=-dirx;
			diry=-diry;
		}
		
	}
}

八、标题:日志统计

小明维护着一个程序员论坛。现在他收集了一份"点赞"日志,日志共有N行。其中每一行的格式是:

ts id

表示在ts时刻编号id的帖子收到一个"赞"。

现在小明想统计有哪些帖子曾经是"热帖"。如果一个帖子曾在任意一个长度为D的时间段内收到不少于K个赞,小明就认为这个帖子曾是"热帖"。

具体来说,如果存在某个时刻T满足该帖在[T, T+D)这段时间内(注意是左闭右开区间)收到不少于K个赞,该帖就曾是"热帖"。

给定日志,请你帮助小明统计出所有曾是"热帖"的帖子编号。

【输入格式】
第一行包含三个整数N、D和K。
以下N行每行一条日志,包含两个整数ts和id。

对于50%的数据,1 <= K <= N <= 1000
对于100%的数据,1 <= K <= N <= 100000 0 <= ts <= 100000 0 <= id <= 100000

【输出格式】
按从小到大的顺序输出热帖id。每个id一行。

【输入样例】
7 10 2
0 1
0 10
10 10
10 1
9 1
100 3
100 3

【输出样例】
1
3

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。
主类的名字必须是:Main,否则按无效代码处理。

思路:单对于时间那个,我想到的是time【i】代表i时刻的点赞次数。但是有未知个id,而且在输出id的时候要求从小到大,我就感觉TreeMap是个好东西,再把id和它相对应的一长串time[]构造类。在下面代码中,一定要注意,不要把时间相减从小到大开始。
这个和上面那个超不超时…我已经很尽力了…没有测试平台,换句话,如果有测试平台,对于后天就要比赛的我来说,…也改不了了…希望读者加油~

package lijie_18;

import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;

public class s_8 {
	static TreeMap<Integer, point> tm;
	public static void main(String[] args) {
		int n,d,k;
		tm=new TreeMap<Integer, point>();
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();//n个帖子
		d=sc.nextInt();//时间段
		k=sc.nextInt();//点赞数
		
		for(int i=0;i<n;i++){
			int time=sc.nextInt();
			int id=sc.nextInt();
			if(tm.containsKey(id)){
				tm.get(id).setTime(time);
			}else{
				point p=new point(id);
				p.setTime(time);
				tm.put(id,p);
			}
		}
		
		Set st=tm.keySet();
		Iterator it=st.iterator();
		while(it.hasNext()){
			point p=tm.get(it.next());
			for(int i=1;i<p.time.length;i++){
				p.time[i]+=p.time[i-1];
			}
			for(int i=p.time.length-1;i>=d-2;i--){
				
				p.time[i]-=p.time[i-d+2];
				
//				if(p.id==10){
					System.out.println(p.time[i]+" "+i+" "+k);
					for(int ii=0;ii<20;ii++){
						System.out.print(p.time[ii]+" ");
					}
					System.out.println();
//				}
				
				if(p.time[i]>=k){
					System.out.println(p.id);
					break;
				}
			}
		}
		
	}
	
}
class point{
	int id;
	int[]time;
	public point(int id){
		this.id=id;
		time=new int[100001];
	}
	public void setTime(int t){
		this.time[t]++;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值