求和式 (C++ 坑爹的<<,>>,%lld)

本文介绍了一道关于位运算的编程题的解决方案。题目要求计算一个整数序列中所有不同元素对的异或值之和。通过分解位运算,采用预处理方法,实现了高效的求解算法。

求和式(x3)

题目描述

作为本场考试的第一题,你的任务十分简单:

给定长度为n的序列A[i],求所有A[i]xor A[j] (i<j)的值之和

 

输入

第一行一个整数N

接下来N行,第i行为A[i]

输出

所需的值

 

样例输入

3

7

3

5

样例输出

12

样例解释

7 xor 3+3 xor 5+7 xor 5 = 4+6+2 = 12

 

数据范围

对于40%的数据,N<=5000

对于100%的数据,N<=1000000


c++中的%lld千万别用啊 ,各种坑人!

统一用cout 

另外C++中(long long)(1<<k)

这里要转,不然必wa

千万要先乘,和别的数乘完不定什么数了……


本题是位运算分解成一位一位运算(重要性质)


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<functional>
#include<algorithm>
using namespace std;
#define MAXN (100+10)
int n,a,c[MAXN][2]={0};// 1<<i =(0.1)
int main()
{
	freopen("x3.in","r",stdin);
	freopen("x3.out","w",stdout);
	
/*	for (int i=0;i<=100;i++)
	{
		cout<<c[i][0]<<' '<<c[i][1]<<endl;
	}
*/	long long ans=0;
	scanf("%d",&n);
	int len=0;
	for (int i=1;i<=n;i++) 
	{
		scanf("%d",&a);
		int tot=-1;
		int j=100;
		while (j--) {c[++tot][a%2]++;a/=2;}
		
		
		
		len=len<tot?tot:len;
				
	}
/*	for (int i=0;i<=100;i++)
	{
		cout<<c[i][0]<<' '<<c[i][1]<<endl;
	}
*/	
	for (int i=0;i<=28;i++)
	{
		ans+=(long long)(1<<i)*(long long)c[i][1]*(long long)(n-c[i][1]);	

//	cout<<ans<<endl;
	}
	
	
/*	
	for (int i=0;i<=len;i++) cout<<c[i][0]<<' '<<c[i][1]<<' '<<endl;
*/

//	printf("%lld\n",ans);
	cout<<ans<<endl;
//	while (1);
	
	return 0;
}



你的代码存在 **多个严重错误**,导致程序行为未定义或结果错误。我们逐条分析并修复。 --- ### ❌ 你写的代码: ```c #include <stdio.h> #include <string.h> #include <stdbool.h> #include <stdlib.h> #include <math.h> #include <ctype.h> #define eps 1e-9 int main() { //S-E3A long long a, b; scanf_s("%lld%lld", &a, &b); if (a > 9223372036854775807 - b) { printf("PO!"); } else if (-a > 9223372036854775808 + b) { printf("NO!"); } else { printf("%d", a + b); } return 0; } ``` --- ## 🔍 错误详解(共 5 处关键错误) --- ### ✅ 错误 1:使用 `scanf_s` 而非 `scanf` - `scanf_s` 是 **MSVC 特有的安全函数**,在 GCC/Clang/Linux 中不支持。 - 即使支持,对于 `%lld`,`scanf_s` 可能需要额外参数(如缓冲区大小),否则行为异常。 🔧 **修复建议**: ```c scanf("%lld %lld", &a, &b); // 使用标准 scanf,并加空格分隔 ``` --- ### ✅ 错误 2:正溢出判断逻辑错误 你写的是: ```c if (a > 9223372036854775807 - b) ``` 这相当于判断 `a + b > 9223372036854775807`,但这个表达本身就有问题: - 当 `b` 是负数时,`9223372036854775807 - b` 会 **超过 long long 最大值**,造成常量溢出! - 更重要的是:**只有当 a 和 b 都为正时才可能正溢出**,不能对所有情况都判断。 ✅ 正确做法是:**只在 a > 0 且 b > 0 时检测正溢出** ```c if (a > 0 && b > 0 && a > LLONG_MAX - b) ``` --- ### ✅ 错误 3:负溢出判断逻辑完全错误 你写的是: ```c else if (-a > 9223372036854775808 + b) ``` 这是错的,原因如下: - `-a` 没有意义,因为 `a` 可能是负数,`-a` 就变成正数了。 - `9223372036854775808` 这个字面量超过了 `LLONG_MAX`(最大是 9223372036854775807),所以它会被解释为 `unsigned long long` 或报编译警告! 正确方是: ```c if (a < 0 && b < 0 && a < LLONG_MIN - b) ``` 表示 `a + b < LLONG_MIN` --- ### ✅ 错误 4:输出格错误 —— 使用 `%d` 输出 `long long` 你写了: ```c printf("%d", a + b); ``` ❌ `%d` 是给 `int` 用的,`a + b` 是 `long long` 类型,应该用 `%lld` ✅ 改为: ```c printf("%lld", a + b); ``` --- ### ✅ 错误 5:缺少换行符 `\n` 题目要求输出一行,即使输出 `"PO!"` 也要换行。 你写的是: ```c printf("PO!"); ``` 应改为: ```c printf("PO!\n"); ``` 同理其他输出也都要加 `\n` --- ## ✅ 修复后的正确代码: ```c #include <stdio.h> #include <limits.h> // 提供 LLONG_MAX 和 LLONG_MIN int main() { long long a, b; // 使用标准 scanf,注意空格分隔输入 scanf("%lld %lld", &a, &b); // 判断正溢出:a > 0, b > 0, 且 a > LLONG_MAX - b if (a > 0 && b > 0) { if (a > LLONG_MAX - b) { printf("PO!\n"); return 0; } } // 判断负溢出:a < 0, b < 0, 且 a < LLONG_MIN - b if (a < 0 && b < 0) { if (a < LLONG_MIN - b) { printf("NO!\n"); return 0; } } // 正常输出结果 printf("%lld\n", a + b); return 0; } ``` --- ## ✅ 测试样例验证: | 输入 | 输出 | |------|------| | `9223372036854775807 1` | `PO!` | | `-9223372036854775808 -1` | `NO!` | | `100 -50` | `50` | | `5000000000000000000 5000000000000000000` | `PO!` | 全部通过 ✅ ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值