HDU2690 Boys and girls

Boys and girls

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 900    Accepted Submission(s): 247


Problem Description
In a big party,there are N people some are boys and the others are girls.Now we will ask them how many girls can they see around the party(expect themselves).And the number will be A1,A2,A3...AN.Then can you tell the total number of girls using the information above?If the information is wrong and doesn't correspond to a unique valid situation,just output"Impossible!".
 

Input
The first line will contain a integer T,then T cases.
At first,there is a integer N,means N people(1<=N<10000),then N integers A1,A2...AN,indicating how many girls he/she sees(except himself/hersels).
 

Output
If the information correspond to a valid situation,output the number of people,otherwise output"Impossible!".
 

Sample Input
  
1 3 2 1 1
 

Sample Output
  
2
 

Author
Teddy
 

Source
 

Recommend
yifenfei   |   We have carefully selected several similar problems for you:   2685  2689  2687  2686  2688 
 

题目意思是说,在一个宴会上,总共有n个人(包括男生和女生),假设每个人都能看到除自己以外的任何人,告诉你每个人看到的女生人数,要你求出宴会上总的女生人数。假设有人说谎或者无法计算出女生人数,则输出Impossible!

题目虽然简单易懂,但是有坑,特别容易wrong answer。

分析:
因为每个人都不能看到自己,所以男生看到的女生人数才是正确的女生人数,而女生看到的人数比实际上少一个。假设有 x 个男生看到的女生人数为 a y 个女生看到的女生人数为 b ,那么当且仅当( a-b ==1 && x+y ==n && a==y)这个表达式成立的时候才可能确定出女生人数。特别注意, 当n==1时是无法判断的,因为不管是男生还是女生看到得都是0。,所以直接输出“Impossible!”。表达能力有限,还是直接看代码吧……%>_<%……

/*
Author:ZXPxx
Memory: 1720 KB		Time: 15 MS
Language: C++		Result: Accepted
*/

#include<cstring>
#include<cstdio>
#include<cmath>

int t,n,a,b,x,y,tmp;
int main() {
    scanf("%d",&t);
    while(t--) {
        scanf("%d",&n);
        bool flag=1;
        a=b=-1; //表示男女生看到的女生人数
        x=y=0;  //累加器,表示男女生人数
        for(int i=0; i<n; i++) {
            scanf("%d",&tmp);
            if(x==0 || tmp==a) {
                a=tmp;
                x++;
            } else if(y==0 && tmp!=a) {
                b=tmp;
                y++;
            } else if(tmp==b)
                y++;
            else if(x && y && tmp!=a && tmp!=b) {
                printf("Impossible!\n");    //出现第三种说法,表示有人说谎
                flag=0;
                break;
            }
        }
        if(!flag)
            continue;
        if(a != -1 && b == -1) {
            if(a == 0 && n == 1) {      //只有一个人无法判断
                printf("Impossible!\n");
                continue;
            }
            if(a == 0 && n > 1 && x == n) {    //当n>1 ,并且 所有人都没看到女生,说明全是男生,则女生人数是0
                printf("0\n");
                continue;
            }
            if(a == n - 1 && x == n) {      //当n>1,且每个人看到的女生数都是n-1,说明全都是女生,即女生数为 n
                printf("%d\n", n);
                continue;
            }
            printf("Impossible!\n");
            continue;
        }
        int da,xiao,fm;
        if(a>b) {
            da=a;
            xiao=b;
            fm=y;
        } else {
            da=b;
            xiao=a;
            fm=x;
        }
        //printf("%d  %d^^^%d\n",da,xiao,fm);
        if(da-xiao ==1 && x + y == n  && fm==da) {
            printf("%d\n",da);
        } else puts("Impossible!");
    }
    return 0;
}



<think>嗯,用户想了解CRC32校验算法的实现和使用方法。我需要先回顾一下CRC32的基本原理,然后考虑如何用简单易懂的中文解释清楚。首先,CRC32是基于循环冗余校验的一种算法,主要用于检测数据传输或存储中的错误。用户可能希望知道它的具体步骤,比如如何初始化、处理数据、异或操作以及最终得到校验值。 根据提供的引用资料,CRC32的核心是多项式除法,但实际中通过查表法优化速度。需要解释生成多项式,比如常见的0xEDB88320,以及初始值、输入输出是否反转这些参数。用户提供的代码片段中有两个版本,一个是逐位计算,另一个是查表法,这可能需要在回答中对比说明,突出查表法的效率优势。 接下来,用户可能关心具体怎么使用这个算法,比如在C语言中的实现步骤,或者如何应用到实际项目中,比如文件校验或网络传输。要分步骤讲解,从初始化到处理每个字节,再到最终计算,可能需要示例代码来辅助说明。同时,注意用户要求行内数学表达式用$...$,比如多项式应该写成$0xEDB88320$这样的格式。 另外,用户的问题里提到生成相关问题,我需要考虑相关的问题可能涉及性能优化、不同生成多项式的影响,或者CRC32与其他校验算法的比较。这些可以作为相关问题放在最后,帮助用户进一步探索。 需要确保回答结构清晰,先讲原理,再讲实现步骤,然后使用方法,最后附上相关问题。同时,引用提供的资料,比如引用[^1]和[^2]来支持解释。要避免技术术语过于复杂,保持语言通俗易懂,同时满足LaTeX格式要求,比如多项式用$符号包裹。检查是否有遗漏的步骤,比如输入反转和输出反转的处理,这在代码示例中有所体现,需要解释清楚这些参数的作用。</think>### CRC32校验算法实现及使用方法 #### 一、CRC32基本原理 CRC32通过多项式除法生成32位校验值,用于检测数据传输或存储中的错误。其核心是生成多项式$G(x)$,常用标准为$0xEDB88320$(反向多项式形式)[^1]。算法流程如下: 1. **初始化**:设置32位寄存器初值为$0xFFFFFFFF$ 2. **数据输入**:逐字节与寄存器异或运算 3. **位移处理**:根据多项式进行循环移位和异或操作 4. **结果取反**:最终值与$0xFFFFFFFF$异或 #### 二、算法实现(C语言) ```c // 查表法实现(高效) uint32_t crc32_table[256]; void init_crc32_table() { for (int i = 0; i < 256; i++) { uint32_t crc = i; for (int j = 0; j < 8; j++) { crc = (crc >> 1) ^ ((crc & 1) ? 0xEDB88320 : 0); } crc32_table[i] = crc; } } uint32_t calc_crc32(uint8_t *data, size_t len) { uint32_t crc = 0xFFFFFFFF; while (len--) { crc = (crc >> 8) ^ crc32_table[(crc ^ *data++) & 0xFF]; } return crc ^ 0xFFFFFFFF; } ``` 此实现通过预先生成的256元素查找表,将时间复杂度从$O(n \cdot 8)$优化到$O(n)$。 #### 三、使用场景及方法 1. **文件校验**:计算文件CRC32值验证完整性 ```bash $ crc32 filename.txt ``` 2. **网络传输**:在数据帧尾部附加4字节校验码 3. **存储系统**:RAID、ZFS等文件系统使用CRC32校验数据块 #### 四、参数配置 | 参数 | 说明 | 标准值 | |---------------|---------------------------|-----------------| | 初始值 | 寄存器初始状态 | 0xFFFFFFFF | | 多项式 | 生成多项式 | 0xEDB88320 | | 输入/输出反转 | 字节处理顺序 | 通常需要反转 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值