2013年JavaA组

1. 世纪末的星期
Calendar类需要注意的两个点:
(1)Calenda.MONTH要比实际月份小1。
(2)Calendar.DAY_OF_WEEK,1代表星期天。

import java.util.Calendar;
import java.util.Scanner;
public class Main
{
 	public static void main(String args[])
 	{
  		int y = 2000;
  		Calendar cal = Calendar.getInstance();
  		cal.set(Calendar.MONTH, 11);
  		cal.set(Calendar.DAY_OF_MONTH, 31);
  		while(true)
  		{
   			int year = y+99;
   			cal.set(Calendar.YEAR, year);
   			if(cal.get(Calendar.DAY_OF_WEEK)==1)
   			{
    				System.out.println(year);break;
   			}
   			y += 100;
  		}
 	}
}

答案:2299

2. 振兴中华
搜索,两条树枝,往右和往下

public class Main
{
 	static int BoundX = 3;
 	static int BoundY = 4;
 	static int cnt=0;
 	public static void main(String args[])
 	{
  		f(0,0);
  		System.out.println(cnt);
 	}
 	static void f(int x,int y)
 	{
  		if(x>BoundX || y>BoundY) return ;
  		if(x==BoundX && y==BoundY) { cnt++; return; }
  		f(x+1,y); //往下
  		f(x,y+1); //往右
 	}
}

答案:35

3. 梅森素数
这道题考的是快速幂乘
比如a的11次幂,11二进制可写为1011
那么就是a^1 * a^2 * a^8
那么就可以不停的幂乘,然后二进制位是1的时候就乘以此时幂乘的结果

import java.math.BigInteger;;
public class Main
{
 	public static void main(String args[])
 	{
  		BigInteger a = new BigInteger("2");
  		int k = 11213;
  		BigInteger ans = Mi(a,k);
  		ans = ans.subtract(BigInteger.ONE);
  		String str = ans.toString();
  		str = str.substring(str.length()-100,str.length());
  		System.out.println(str);
 	}
 	static BigInteger Mi(BigInteger a,int b) //幂乘 a^b
 	{
  		BigInteger ret = new BigInteger("1");
  		while(b>0)
  		{
   		if((b&1)==1) ret = ret.multiply(a); //二进制位为1时,乘上此时的a
   		a = a.multiply(a); //a自身幂乘,翻倍
   		b = b>>1;
  		}
  		return ret;
 	}
}

答案:8586718527586602439602335283513944980064327030278104224144971883680541689784796267391476087696392191

4. 颠倒的价牌
本题枚举+判断即可。
主要操作在数的翻转上
可以将数字转成String,再转成char数组,一位一位判断,首末为0,则不能倒过来,某位为3,4,7的一种也不能倒过来,某位是6,9,转为9,6.
最后再将char数组转成String,利用StringBuffer的reverse()函数翻转一下。

public class Main
{
 // 能倒过来的数字有 1 2 5 6 8 9 0  , 不能倒过来的有3 4 7
 // 倒过来为         1 2 5 9 8 6 0 ,也就是只能6,9倒过来
 public static void main(String args[])
 {

  	for(int x=1000; x<=9999; x++)
  	{
   		for(int y=x+1; y<=9999; y++)
   		{
    		int rx = reverse(x);
    		int ry = reverse(y);
    		if(rx==0||ry==0) continue;
    		int dx = rx-x;
    		int dy = ry-y;
    		if(dy>-300 && dy<-200 && dx>800 && dx<900 && (dx+dy)==558)
    		{
     		System.out.println(x+" "+y);
    		}
   		}
  	}
 }
 static int reverse(int num)
 {
  	String s = String.valueOf(num);
  	char[] ch = s.toCharArray();
  	if(ch[0]=='0'||ch[3]=='0') return 0; //首位末尾不能为0
  	int temp=num;
  	int cnt=3;
  	while(temp>0)
  	{
   	int mod = temp%10;
   	if(mod==3||mod==4||mod==7)  return 0; // 3,4,7不能倒
   	if(mod==6) ch[cnt] += 3;
   	else if(mod==9) ch[cnt] -= 3;
   	temp = temp/10;
   	cnt--;
  	}
  	StringBuffer buf = new StringBuffer(new String(ch));
  	buf.reverse(); //翻转一下
  	return Integer.parseInt(buf.toString());
 }
}

输出:
1061 9088
2062 9088
5065 9088
6069 9088
8068 9088
9066 9088
所以赔钱的价格为9088。

5. 三部排序
答案:p++

6. 逆波兰表达式
这个可以去看下数据结果的前缀、中缀、后缀表达式。
填空位置的上一句 int[] v1 = evaluate(x.substring(1)); 会在遇到第一个不是运算符的数字时返回,那v2应该接下去处理。
答案:evaluate(x.substring(1+v1[1]))

7. 错误票据
这道题主要考数据的处理。首先输入每行的数据长度也即票据号个数不同,这点用String类即可处理:用String接收一行数据,然后用split()函数分割数据,需注意的是分割是以若干个空格,split(regex)中的regex应该为"\s+"(这个可以去百度Java的正则表达式匹配)。
然后是存储,因为不知道票据总个数,所以用List存储比较好,把分割出来的字符串转成Integer,add()到List中。
处理完输入,对List排序(用Collections.sort()即可),然后找断号和重号即可。

import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
public class Main
{
 	static int N;
 	public static void main(String args[])
 	{
  		Scanner sc = new Scanner(System.in);
  		N = sc.nextInt();
  		sc.nextLine(); //先吃掉一个换行符
  		List<Integer> ls = new ArrayList<Integer>();
  		String str;
  		String[] sp;
  		for(int i=0;i<N;i++)
  		{
   			str = sc.nextLine();
   			sp = str.split("\\s+");  //以若干个空格分割
   			for(int j=0;j<sp.length;j++)
   			{
    			ls.add(Integer.parseInt(sp[j]));
   			}
  		}
  		//输入处理完
  		//排序
  		Collections.sort(ls);
  		//遍历找断号和重号
  		int m=0,n=0;
  		for(int i=1;i<ls.size();i++)
  		{
   		if(ls.get(i)-ls.get(i-1)==2) m = ls.get(i)-1; //断号
   		else if(ls.get(i)-ls.get(i-1)==0) n = ls.get(i); //重号
  		}
  		System.out.println(m+" "+n);
 	}
 
}

8. 带分数
这道题可以先对1~9全排列,然后对排列的每种情况做判断,从第一个数的位数为1开始,到第一个数的位数与N的位数相同。

import java.util.Scanner;
public class Main
{
	 static int N;
	 static int Len;
	 static int cnt=0;
	 public static void main(String args[])
	 {
	  Scanner sc = new Scanner(System.in);
	  N = sc.nextInt();
	  Len = getLen(N);
	  char[] a = new char[] {'1','2','3','4','5','6','7','8','9'};
	  mySort(a,0);
	  System.out.println(cnt);
	 }
	 static int getLen(int n)
	 {
		  int ret=0;
		  while(n>0)
		  {
		   n=n/10;
		   ret++;
	 }
	  return ret;
	 }
	 static void mySort(char a[],int k)//1~9全排列
	 {
	  	if(k==9) {
	   		f(a); return ;
	  	}
	  	for(int i=k;i<9;i++)
	  	{
	   		{char t=a[i];a[i]=a[k];a[k]=t;}
	   		mySort(a,k+1);
	   		{char t=a[i];a[i]=a[k];a[k]=t;}
	  	}
	 }
	 static void f(char ch[])
 	{
  		String str = new String(ch);
  		for(int l=1;l<=Len;l++)  //第一个数的长度
  		{
   			int half=(9-l)/2;
   			String s1 = str.substring(0, l);//取第一个数
   			int n1 = Integer.parseInt(s1);
   			for(int h=half;h<=half+Len/2;h++) //第二个数的长度
   			{
    				String s2 = str.substring(l,l+h);//取第二个数
    				String s3 = str.substring(l+h,9);//取第三个数
    				int n2 = Integer.parseInt(s2);
    				int n3 = Integer.parseInt(s3);
    				double d = n2*1.0/n3;
    				if(n1+d==N) //判断
    				{
     					cnt++;
    				}
   			}
 		 }
 	}
}

9. 剪格子
深搜+减枝
int[] dx = {-1,1,0,0};
int[] dy = {0,0,-1,1};
根据 x+dx[i] 和 y+dy[i] 控制往上下左右四个方向搜索。
然后记录走过格子的个数cnt,以及走过格子的数字和sum。
如果sum>数字和的一半,不用再继续搜了,减枝。
如果sum==数字和的一半,找到符合的剪法了,判断左上角包含的格子是不是最小的,不断更新min的值。

import java.util.Scanner;
public class Main
{
 static int M,N;
 static int[][] a;
 static boolean[][] vis; //标记走过的格子
 static int Half=0;
 static int[] dx = {-1,1,0,0}; //上下左右走 x,y坐标的变动
 static int[] dy = {0,0,-1,1};
 static int min=100;
 public static void main(String args[])
 {
  	Scanner sc = new Scanner(System.in);
  	M = sc.nextInt();
  	N = sc.nextInt();
  	a = new int[N][M];
  	vis = new boolean[N][M];
  	int sum = 0;
  	for(int i=0;i<N;i++)
   		for(int j=0;j<M;j++) {
    			a[i][j]=sc.nextInt();
    			sum+=a[i][j];
   		}
  	sc.close();
  	if(sum%2==1) { //无法分割
   		System.out.println("0"); return;
  	}
  	Half = sum/2;
  	f(0,0,0,0);
  	System.out.println(min);
  
 }
 static void f(int x,int y,int sum,int cnt) //(x,y)是当前格子的坐标,sum是走过格子的数字和,cnt是走过格子的个数
 {
  	if(sum>Half) return;
  	if(sum==Half) {
   		min = (cnt<min)?cnt:min;
   		return ;
  	}
  	vis[x][y]=true;
  	for(int i=0;i<4;i++)
  	{
   		int nx = x+dx[i];
   		int ny = y+dy[i];
   		if(nx<0||nx>=N||ny<0||ny>=M||vis[nx][ny]==true) continue;
   
   		f(nx,ny,sum+a[x][y],cnt+1);
   
  	}
  	vis[x][y]=false;
 }
 
}

10.大臣的旅费
这道题考点是求 “ 图的直径 “
图的直径的求法,就是任意确定一个点,找距离该点的最远点,记这个最远点为temp,再找temp的距离最远点,temp到它最远点的距离就是图的直径。
由于本题说了任意两个城市都能到达,且高速路的条数为n-1条,那这个图必然是主树。该图内肯定不会有闭环,那么处理起来就方便了,搜索时就只要保证下个节点不是当前节点的前一个就行,也就是当前为now,下个为next,前一个为from,只要next!=from,next这个点就可以往下搜。

import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;
public class Main
{
 static class Node
 {
  	int id;
  	int weigth;
  	public Node(int id,int weigth)
  	{
   		this.id=id;
   		this.weigth=weigth;
  	}
 }
 static int n;
 static List<Node>[] ls ;
 static int max=0;
 static int temp;
 public static void main(String args[])
 {
  	Scanner sc = new Scanner(System.in);
  	n = sc.nextInt();
  	ls = new List[n+1];
  	for(int i=0;i<=n;i++)
   		ls[i] = new ArrayList<Node>();
  	for(int i=1;i<n;i++)
  	{
   		int f = sc.nextInt();
   		int t = sc.nextInt();
   		int w = sc.nextInt();
   		ls[f].add(new Node(t,w));
   		ls[t].add(new Node(f,w));
  	}
  	f(1,0,0); //求距离1的最远点,得到temp
  	f(temp,0,0); //求距离temp的最远点,结束后的max为直径
  	System.out.println(max*10+max*(max+1)/2);
 }
 static void f(int index,int from,int sum) //一个点到距离它最远点,temp在结束函数调用后为那个最远点,max为它们之间的距离
 {
  	boolean flag=true;  //假设一进来认为该节点为叶子节点,就是不能往下搜了
  	for(int x=0;x<ls[index].size();x++)
  	{
   		int next = ls[index].get(x).id;
   		if(next==from) continue;
   		flag = false; //还能往下搜,不是叶子节点,改变标记
   		f(next,index,sum+ls[index].get(x).weigth);
  	}
  	if(flag) //确定是叶子节点
   		if(sum>max) { max=sum; temp=index;}
 }
}

这代码格式简直逼死强迫症,自己加Tab加的无语,如果有知道怎么调的,麻烦评论里教我下,谢谢~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值