1519: 小P参加相亲大会(ZZULIOJ)

简述

这两天真的是恶心到了我,本身以前也会偶尔写写算法的题目的,那个时候用的是C语言,没有用别的语言写比赛的题目,这两天正好看到了一个oj上面的比赛题,索性就写了一下,起初我是用java写的,不论怎么写都是时间超限,我当时想的是,可能是我自己的算法本身存在问题,后来我就上网百度了一下,度娘是个号东西啊,我百度了一下,找到了一个首屈一指的博客,我就兴致勃勃进去看了一下,我去,一看方法和我的差不多,就是人家是用C语言写的,我是用java语言写的,诶呦,顿时心里那个难受的呦!
后来,我又找到了这道题官方给的解答,当然和我找的博客的解答是不一样的,按照官方的解答,我当时没有看太懂,主要是能力有点太差了,然后我就又找上了度娘,这次我换了一个委婉的方式去搜索,这次我又搜索到了一个博客来解释,这个解释核心的思想就和官方的解释是一致的,之后我又重新拿起了java语言编写了一下,诶呦,我去,还是超时,这时,我果断把我的java代码改为了C代码,之后C过了,我为了优化java使其能过的时候,我偶然间又发现了我之前使用官方的解释提交的那个过了的C的代码的bug,实际上那个C过了的是有问题的,顿时,心里又是一顿难受。
下面我分享一下我的经历,仅此看看吧!

题目

1519: 小P参加相亲大会
时间限制: 2 Sec 内存限制: 16 MB
提交: 428 解决: 60
[提交] [状态] [讨论版] [命题人:外部导入]
题目描述
小P最近人生得意,去参加了一次相亲大会,相亲大会上每个人有一个密码牌(密码牌上的密码是一个正整数m,m<231 ),相互之间在交流之前先交换密码牌,密码牌上的密码可能相同,也可能不同,如果相同,两人牵手离开,如果不保同,各自再寻找下一位,保证最后只有1个人或2个人留下来。

输入
第一行两个数 n,k (n≤3000000,1≤k≤2),n表示参加相亲大会的人数,接下来 n行每行一个正整数表示相亲大会上每一个人的密码,k表示最后留在相亲大会的人数。
输出
从小到大输出一行 k个数,表示相亲不成功留在相亲大会人的密码,中间用空格分隔。
样例输入 Copy
3 1
2
2
2
样例输出 Copy
2
提示
对于40% 的数据,保证 k=1。

对于20%的数据,保证n≤100

对于100%的数据,保证 n≤3000000,ai<231。

// 这个是我之前最早写的一种,也是超时的一种

import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;

public class Main {
	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);
		Comparator com = new Comparator() {

			@Override
			public int compare(Object o1, Object o2) {
				Integer i1 = (Integer) o1;
				Integer i2 = (Integer) o2;
				return i1 - i2;
			}

		};
		TreeSet<Integer> datas = new TreeSet<Integer>(com);

		int n, k;
		n = sc.nextInt();
		k = sc.nextInt();
		for (int i = 0; i < n; i++) {
			Integer m = sc.nextInt();
			if (datas.contains(m)) {
				datas.remove(m);
			} else {
				datas.add(m);
			}
//			System.out.println(datas.toString());
		}
		for (int i = 0; i < k; i++) {
			Integer x = datas.first();
			datas.remove(x);
			if (i == 0) {
				System.out.print(x);
			} else {
				System.out.print(" " + x);
			}
		}

		sc.close();
	}
}

从此往下面的开始就是oj给我开的玩笑的开始
先给出第一队的玩笑,就是代码算法思想相同的C和JAVA,C过了,java不能过

// 这个对应的C++的版本是没有问题的,可以在玩我的那个oj上面通过,
// 目前是没有什么问题存在的
import java.util.Arrays;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);
		int n, k;
		n = sc.nextInt();
		k = sc.nextInt();

		int[] datas = new int[n];
		for (int i = 0; i < datas.length; i++) {
			datas[i] = sc.nextInt();
		}

		Arrays.sort(datas);
		boolean flag = true;
		for (int i = 0; i < datas.length; ) {
			if ((i+1) < datas.length && datas[i] == datas[i + 1]) {
				i += 2;
			} else {
				if (flag) {
					System.out.print(datas[i++]);
					flag = false;
				} else {
					System.out.print(" " + datas[i++]);
				}
				k--;
				if (k == 0) {
					break;
				}
			}
		}
		sc.close();
	}
}

从此开始第二段笑话,也就是模仿另一种方法最后给出的也是C可以过,JAVA又不可以过,并且这种方法是存在问题的,但是oj 这个判题系统没有发现,下面我会给出那个可以测出这个过了的程序的有问题的实例。

// 这个是有问题的,不能通过的实例是:10 2 7 3 1 1 2 2 4 4 5 5
// 大家可以尝试一下这个程序,输出的结果是错误的,与题意应该是不符合的。
// 但是这个程序的强大之处是在oj上面过了
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int n, k, ret = 0, i;
    scanf("%d%d", &n, &k);

    int a[3000009];
    for (i = 0; i < n; i++)
    {
        scanf("%d", &a[i]);
        ret ^= a[i];
    }

    if (k == 1)
    {
        printf("%d\n", ret);
    }
    else
    {
        // int inter = Integer.toBinaryString(ret).toCharArray().length;
        int inter = ret - (ret & (ret - 1));
        int retA = 0;
        int retB = 0;

        for (i = 0; i < n; i++)
        {
            int b = (a[i] >> (inter - 1)) % 2;
            if (b == 0)
            {
                retA ^= a[i];
            }
            else
            {
                retB ^= a[i];
            }
        }
        if (retA < retB)
            printf("%d %d\n", retA, retB);
        else
            printf("%d %d\n", retB, retA);
    }
    return 0;
}

下面这个JAVA程序和上面紧接着的那个C程序大致思想是一致的,但是就是,他没过,并且下面的这个JAVA程序时没有上面的那个实例 的错误的,也就是说在这个算法下是没有错误的。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);
		int n, k, ret = 0;
		n = sc.nextInt();
		k = sc.nextInt();

//		System.out.println("@@@:" + n);
		
		int[] a = new int[n];
		for (int i = 0; i < a.length; i++) {
			a[i] = sc.nextInt();
			ret ^= a[i];
		}

		if (k == 1) {
			System.out.println(ret);
		} else {
			 int inter = Integer.toBinaryString(ret).toCharArray().length;
//			int inter = ret - (ret & (ret - 1));
			int retA = 0;
			int retB = 0;

//			System.out.println("inter:" + inter);
			
			for (int i = 0; i < a.length; i++) {
				int b = (a[i] >> (inter - 1)) % 2;
				if (b == 0) {
					retA ^= a[i];
				} else {
					retB ^= a[i];
				}
			}
			if (retA < retB)
				System.out.println(retA + " " + retB);
			else
				System.out.println(retB + " " + retA);
		}

		sc.close();
	}

}

最后再说一下,JAVA关于那个Integer的小点吧,我室友遇到的错误,虽然我也不知道他为啥要用Integer,但是他就是用了,在此就提一下吧,毕竟也是因为的这道题

// 这个程序对应的C也是通过的,但是就是使用JAVA的时候报答案错误
// 这实际上是Integer的问题,下面有大致的解释
import java.util.Arrays;
import java.util.Scanner;
public class Main {
    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        int ans[] = new int[2];
        int number = 0;
        Integer[] arr = new Integer[n];
        for(int i = 0 ; i < n;i++){
            arr[i] = sc.nextInt();
        }
        Arrays.sort(arr);
        int j = 0;
        for(int i = 0 ;i<n;i=j) {
            int flag =0;
            for( j=i; j < n ; j++) { 
                if(arr[i]==arr[j]) {
                    flag++;
                }
                else {
                    break;
                }
            }
            if(flag%2==1&&number<=1) {
                if(arr[i]!=ans[0]||arr[i]!=ans[1]) {
                    ans[number] = arr[i];
                    number++;
                }
                 
            }
        }
        for(int in:ans) {
            if(in != 0) {
                System.out.print(in + " ");
            }
        }
        sc.close();
    }
}

Integer 数据类型
Integer 一个整型数据用来存储整数,整数包括正整数,负整数和零。
整型常量采用十进制整数表示。如 1991,0,-123等等都是整型常量。而52.0或131.4都不是整型常量。
Integer 变量存储为最接近编译环境的长度,例如在32位的编译环境下,Integer为32位,其范围为 -2^15 到 2^15-1 之间。
VB中Integer 的类型声明字符是百分比符号 (%)。Pascal中就是integer。在C语言中被缩写成为int。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值