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

相关推荐
奋斗的小花生1 小时前
c++ 多态性
开发语言·c++
pianmian11 小时前
python数据结构基础(7)
数据结构·算法
闲晨1 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
UestcXiye3 小时前
《TCP/IP网络编程》学习笔记 | Chapter 3:地址族与数据序列
c++·计算机网络·ip·tcp
好奇龙猫3 小时前
【学习AI-相关路程-mnist手写数字分类-win-硬件:windows-自我学习AI-实验步骤-全连接神经网络(BPnetwork)-操作流程(3) 】
人工智能·算法
霁月风4 小时前
设计模式——适配器模式
c++·适配器模式
sp_fyf_20244 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘
香菜大丸4 小时前
链表的归并排序
数据结构·算法·链表
jrrz08284 小时前
LeetCode 热题100(七)【链表】(1)
数据结构·c++·算法·leetcode·链表
oliveira-time4 小时前
golang学习2
算法