简述
这两天真的是恶心到了我,本身以前也会偶尔写写算法的题目的,那个时候用的是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。