GCD Compression

题目大意:

有一个数组 a 其中有 2n 个数,把它压缩进数组 b,b 的大小是 n-1。
所谓的“压缩”指的是两种操作:

  • 首先舍弃 a 当中的两个数(你可以任意选择)。
  • 然后每次取出剩下的数组 a 当中的两个数,把他们的和放入数组 b 当中。

要求最终 b 数组中所有数的最大公约数(gcd)要大于 1,即 gcd{b_1,b_2,...,b_n-1}>1
请你把你每一次从 a 中取出的两个数在原来的 a 中的下标输出,如果答案不唯一输出任意一种即可。

题解:

如题目所说,保证每一组数据都有解,那么为什么一定有解呢?

  首先,给定的序列里,数的种类可以分成奇数和偶数,对于奇数来说,每两个奇数的和是偶数,对于偶数来说,每两个偶数的和也一定是偶数。因此,我们只需要将2n-2个数取出,合并,使每个数都为偶数,即可保证最大公因数至少为二

  那么,我们应该如何取这2n-2个数呢?
  如何取数,受制于数列里奇数和偶数的个数。因为数列里的数的总数为2n为偶数,所以如果奇数的个数为奇数,那么偶数的个数也为奇数,这时候只需要奇数偶数分别扔一个出去即可保证两两之间有符合要求的匹配。如果奇数的个数为偶数,偶数的个数也为偶数,那么随便选奇数或偶数扔两个数出去即可(前提是你选中的这种数的类型(奇数or偶数)所包括的数的个数至少大于或等于二

点击查看代码
#include<bits/stdc++.h> using namespace std; const int MAXN = 2005; struct p{ int num,pos; p(){} p(int nnum,int ppos){ nnum = nnum; pos = ppos; } };//记录数列中每个数的大小和下标 vector<p> j,o;//j记录奇数,o记录偶数 int t,n,a[MAXN],cntj,cnto; int main(){ cin >> t; while(t--){ j.clear(); o.clear(); memset(a,0,sizeof a); cin >> n; for(int i = 1; i <= 2 * n; i++){ cin >> a[i]; if(a[i] % 2 == 1)j.push_back(p(a[i],i));//存数 else o.push_back(p(a[i],i)); } if(j.size() % 2 == 0 && o.size() % 2 == 0){//判两种类型的数的个数的情况并进行相应的处理 for(int i = 2; i < j.size(); i+=2){ cout << j[i].pos << " " << j[i + 1].pos<< "\n"; } for(int i = 0; i < o.size(); i+=2){ cout << o[i].pos<< " " << o[i + 1].pos << "\n"; } } else if(j.size() % 2 == 1 && o.size() % 2 == 1){ for(int i = 1; i < j.size(); i+=2){ cout << j[i].pos << " " << j[i + 1].pos << "\n"; } for(int i = 1; i <o.size(); i+=2){ cout << o[i].pos<< " " << o[i + 1].pos<< "\n"; } } } }

__EOF__

本文作者Never Gonna Give You Up!
本文链接https://www.cnblogs.com/CZ-9/p/16468029.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   腾云今天首飞了吗  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示