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

相关推荐
青椒大仙KI11几秒前
24/9/19 算法笔记 kaggle BankChurn数据分类
笔记·算法·分类
^^为欢几何^^4 分钟前
lodash中_.difference如何过滤数组
javascript·数据结构·算法
豆浩宇4 分钟前
Halcon OCR检测 免训练版
c++·人工智能·opencv·算法·计算机视觉·ocr
WG_1713 分钟前
C++多态
开发语言·c++·面试
浅念同学20 分钟前
算法.图论-并查集上
java·算法·图论
何不遗憾呢29 分钟前
每日刷题(算法)
算法
立志成为coding大牛的菜鸟.33 分钟前
力扣1143-最长公共子序列(Java详细题解)
java·算法·leetcode
鱼跃鹰飞33 分钟前
Leetcode面试经典150题-130.被围绕的区域
java·算法·leetcode·面试·职场和发展·深度优先
liangbm339 分钟前
数学建模笔记——动态规划
笔记·python·算法·数学建模·动态规划·背包问题·优化问题
潮汐退涨月冷风霜44 分钟前
机器学习之非监督学习(四)K-means 聚类算法
学习·算法·机器学习