Codeforces Round 893 (Div. 2) C

这场我vp的,vp的依托,我1700的人,打div2只写了一题。不知道怎么评价。

B题思路不够清晰,思维审慎又要再强调几遍了。想的过程太急了,直接导致了我写了很久,重构了两边,最后写的一团乱麻,没交上去。我以为这个问题被解决了,就不会再犯了。看了只要不注意就会犯啊。其实这样才正常嘛。

C题链接

C题构造,没有思路就很麻烦,还连续看错了两遍题目。
GCD的题目,我还是不够熟悉。
很明显,每次加入一个数字产生的最大贡献就是1,我们可以考虑怎么样让每次都尽可能产生贡献。
如果一个数字要和另一个数字取GCD并且得到它本身,那最方便的就是这两个数字一样。否则就是给他乘个2。
很明显,这题就是这样。我要每次都产生价值,那就是每次都尽可能利用上每个数字,我直接尝试让这个位置产生的gcd变成上个数字本身,那下个数字就是上个数字乘2,否则就是没有意义的。这个构造要是想到了,就很好证明。但是不好想。

我想不到的一个原因就是对GCD不够熟悉。我又再次误入歧途,求了质因数。
其实质因数和GCD的关系。。真的是很有限。我应该关注的是因子。这题的一个很重要的思路就是,贡献最大化。这个贪心的去贡献在最后可以被证明是最优的,但是在开始其实是没有什么头绪的。但是既然要求我们求最大的贡献,那想想怎么取能够让贡献先尽可能的大是绝对没错的。这题需要这个思路。
记录下来,这个很重要。

而最后的答案就是这样。对每个没有被取过的数字乘2,看看是否被占用,如果没用过,那就放上去。这样可以证明一定会产生1的贡献。
这就够优秀了。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read() {
	char c=getchar();int a=0,b=1;
	for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
	for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;return a*b;
}
int vis1[100001],vis2[100001];
int gcd(int a,int b)
{
	if(b==0)return a;
	return gcd(b,a%b);
}
int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int T=read();
	while(T--)
	{
		int n=read();
		int last=1,ans=0;
		for(int i=1;i<=n;i++)vis1[i]=vis2[i]=0;
		for(int i=1;i<=n;i++)
		{
			int now=i;
			while(now<=n)
			{
				if(vis1[now]==0)
				{
					cout<<now<<' ';
					vis1[now]=1;
				}
				now*=2;
			}
		}
		cout<<endl;
	}
	return 0;
}

思维审慎,注重思路。不要急,不要慌。

posted @ 2024-04-06 22:14  HL_ZZP  阅读(8)  评论(1编辑  收藏  举报