题目描述

在大学里一定不能旷课,一天某个老师去上课用自己的火眼金睛感觉教室里有一个学生没有来,于是他就叫学生们报出自己的学号。

已知这个班上的学号是从1开始连续编号的,并且告诉你这个班上有多少人,想问问你到底是谁没有来。

输入描述:

输入数据共两行,第一行为一个整数N,表示班上的学生数量。

2≤N≤200000
第二行 为一行N-1个整数,表示已经来的学生的学号,学号将按乱序给出。

分析:

1、可以将所有同学的学号相加,减去已经来的学生的学号,最后剩下的就是没来的学生的学号。
2、如果数据范围进一步扩大,相加可能会超出表示范围,可以采用异或的方法:
已知  x ^ y ^ y = x
将所有学生学号异或已经来的学生学号,最后剩下的是没来的学生的学号。
#include<iostream>
using namespace std;
//x ^ y ^ y = x
int main(){
    int n;
    cin >> n;
    int num;
    int sum = 0;
    for(int i = 1; i < n; i++){//因为只有n-1个学生来了,所以循环范围1~n-1
        //cin >> num;
        scanf("%d", &num);    //cin用时长,数据太多时用scanf()输入更快
        sum = (sum ^ i ^ num);
    }
    cout << (sum ^ n) <<endl;//最后异或上第n个学生的学号,才是最终结果
}

扩展:

如果题目改为两个同学没来,同样使用异或,得出两个没来的同学的异或和。
异或和为1的位数两个同学的学号二进制此位相反。
取其中的一个1,找出此位为1和此位为0的同学,将他们分成两部分,则每一部分的同学中有一个同学没来,问题回到原题。