1916_C. Training Before the Olympiad_数学_余数_归纳_奇数偶数_贪心_博弈论

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

void solve()
{
	int n,a,cnt=0;
	cin>>n;

	long long s=0;
	for(int i=1;i<=n;i++)
	{
		cin>>a;
		s+=a;
		
		if(a&1)
			cnt++;
		
		if(i==1)
			cout<<a<<" ";
		else
			cout<<s-(cnt/3+(cnt%3==1))<<" ";
	}
	cout<<endl;
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int t;
	cin>>t;
	
	while(t--)
		solve();
	
	return 0;
}

上面是修饰过后的代码,感觉非常简短,没用数组啥的,只用了一些变量,一层循环写完了,也没有把过程一步一步分开写

下面是最开始的代码

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

const int N=2e5+10;

int a[N];//cnt 存奇数的个数
long long s[N];

void solve()
{
	int n;
	cin>>n;
	
	int cnt=0;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		s[i]=s[i-1]+a[i];
		
		if(a[i]%2!=0)
			cnt++;
		
		if(i==1)
			cout<<a[i]<<" ";
		else
		{
			long long ans=s[i];
			ans=ans-(cnt/3+(cnt%3==1));
//			if(i==4)
//				cout<<endl<<"4%3==1的数值是"<<(cnt%3==1)<<endl;
			cout<<ans;
			if(i!=n)
				cout<<" ";
		}
	}
	cout<<endl;
	
//	for(int i=1;i<=n;i++)
//		cin>>a[i];
//	
//	cout<<a[1]<<" ";
//	
//	int cnt=0;
//	for(int i=1;i<=n;i++)
//	{
//		s[i]=s[i-1]+a[i];
//		if(a[i]%2!=0)
//			cnt++;
//	}
//	for(int i=2;i<=n;i++)
//	{
//		int ans=s[i];
//		ans=ans-(cnt/3+(cnt%3==1));
//		if(i==2)
//			cout<<"i=2的时候奇数的个数是:"<<endl<<cnt<<endl;
//		cout<<ans;
//		if(i!=n)
//			cout<<" ";
//	}
//	cout<<endl;
//	
//	memset(a,0,sizeof a);
//	memset(s,0,sizeof s);
	//memset(cnt,0,sizeof cnt);
	//判断奇数偶数个数就行
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int t;
	cin>>t;
	
	while(t--)
		solve();
	
	return 0;
}

中间错了几次,主要是因为 long long ,还有我想要用布尔值直接表示,就不需要用一个条件判断,但是之前没有用好,少加了个括号,然后不断输出调试才发现问题

该题我写了好久,看了一下榜单,很多分数很高的人,几分钟就写出了该题

我先是模拟样例理解题意,然后是自己弄几个数据归纳规律

发现全是偶数的话,答案就是总和

两个奇数相加,答案是偶数,两个偶数相加,答案也是偶数,一个奇数一个偶数,这样的组合会让答案减小一

先开始的人要使得答案尽可能大,就是要尽可能避免使用 一个奇数,一个偶数这种组合

另一个人要使得答案尽可能小,就是要尽量使用一个奇数一个偶数的组合,使用一次,可以使得答案减小一,两个奇数的和是偶数,事实上偶数不会影响答案,可以通过模拟样例发现这个规律

我们首先统计奇数的个数,我开始以为是奇数的个数的奇偶性影响答案,试了几个数据发现不是这回事,我试了有7,8,9,10,11,12,13,14,15个奇数对应应该减小的答案,发现是,3,2,3,4,3,4,5,4,5

三个一个循环,想让答案大就每一次操作两个奇数,想让答案小就每次操作一个奇数一个偶数,两个奇数操作后变成了一个偶数,刚好和后面一个奇数操作,这就是博弈!

注意任何操作之后,两个数字都会变成一个偶数,因为向下取整之后乘了二

归纳观察可以发现,奇数出现次数记作 cnt 的话,cnt/3 表示的是需要减少的答案的数目, cnt%3 的结果是 1 的话,表示多了一个奇数,还需要多减小 1 的答案(我的代码里面用了一个比较简短的写法,记得要加括号)

统计奇数个数,a&1 表示的是该数字是奇数,因为二进制表示的话,奇数的二进制的最低位一定是 1 ,1&1==1,偶数的最低位一定是 0,比用模二判断要快一些,因为计算机底层用的是二进制编码

有 1e5 个 1e9 的数字,所以他们的和一定超过了 int 能表示的数据范围,所以要使用 long long

相关推荐
Swift社区1 分钟前
LeetCode - #139 单词拆分
算法·leetcode·职场和发展
Kent_J_Truman33 分钟前
greater<>() 、less<>()及运算符 < 重载在排序和堆中的使用
算法
IT 青年1 小时前
数据结构 (1)基本概念和术语
数据结构·算法
Yang.991 小时前
基于Windows系统用C++做一个点名工具
c++·windows·sql·visual studio code·sqlite3
熬夜学编程的小王1 小时前
【初阶数据结构篇】双向链表的实现(赋源码)
数据结构·c++·链表·双向链表
zz40_1 小时前
C++自己写类 和 运算符重载函数
c++
Dong雨1 小时前
力扣hot100-->栈/单调栈
算法·leetcode·职场和发展
六月的翅膀1 小时前
C++:实例访问静态成员函数和类访问静态成员函数有什么区别
开发语言·c++
SoraLuna2 小时前
「Mac玩转仓颉内测版24」基础篇4 - 浮点类型详解
开发语言·算法·macos·cangjie