首页 > 其他分享 >P9575 「TAOI-2」喵了个喵 Ⅳ

P9575 「TAOI-2」喵了个喵 Ⅳ

时间:2023-08-22 19:46:46浏览次数:49  
标签:那么 gcd 奇数 int lowbit P9575 偶数 TAOI

思路

考试的时候打死没想出来,一直在想暴力和质因数分解,我实在是太弱了,比赛后看了官方题解才恍然大悟,于是来写篇题解。

首先是一些特殊点:

  1. 当 \(n\) 是偶数时,显然 \(x\) 可以取 \(1\),这样 \(\gcd\) 就都是 \(1\),然后随便平分就好了。恭喜你,你获得了 \(2\) 分。

  2. 当 \(n\) 不是偶数,且 \(a_i\) 均为奇数,那么无论怎么 \(\gcd\) 都是奇数,所以 \(\gcd\) 之和也一定是奇数,那必然无法划分,那么就是无解。恭喜你,你又获得了 \(8\) 分(蒟蒻的我比赛的时候连这都没想到,痛失 \(8\) 分)。

  3. 当 \(n\) 不是偶数时,这种情况比较难办,下面专门详细讲解。

首先容易发现 \(x=1\) 时,\(\gcd\) 之和就是 \(n\),但是 \(n\) 为奇数,显然不满足要求。

这样,我们可以尝试增大 \(x\) 的倍数。

假设扩大了 \(x\) 共 \(k\) 倍,那么 \(\gcd(a_i,x)\) 的变化一定是扩大 \(l\) 倍,其中 \(l\) 是 \(k\) 的因子,那么对于和的贡献是 \((l-1)\times \gcd(a_i,x)\)。

这样的话,只有 \(l\) 为偶数,\(\gcd(a_i,x)\) 为奇数时,贡献才能增加奇数,才能使和变为偶数。

所以我们扩大倍数扩大奇数倍是毫无作用的,扩大倍数含奇数因子意义也不大,所以我们要扩大的倍数只有 \(2^s,s\in \mathbb{Z}\) 最有效。

那么 \(s\) 取几最合适呢?

有两种方法,第一种是挨个试,试到 \(2^s\) 比最大的 \(a_i\) 还要大为止,不过没有试过,不清楚会不会 TLE。

第二种,我们可以随意构造一个同时含奇数、偶数的数列,如果奇数的个数奇数个,那就意味着 \(x\) 不能取 \(1\),如果把 \(x\) 扩大 \(2\) 倍,奇数的个数不会变,其余的 \(\gcd\) 要么不变,要么也扩大 \(2\) 倍,和仍然是偶数,所以这种情况一定是无解。那么,我们可以尝试把问题归纳到这种情况解决。

那么,怎么找到那个数呢,这里推荐一种比较方便的方法,那就是 \(lowbit\)。

\(lowbit(x)\) 可以取出 \(x\) 在二进制形式下的最末位的 \(1\) 以及后面的 \(0\)。举个例子,\(12\) 的二进制形式是 \(1100\),那么 \(lowbit(12)=4\)。(\(4\) 的二进制形式是 \(100\))

那么,怎么计算 \(lowbit\) 呢?

其实很简单,只需要一行代码就能搞定:inline int lowbit(int x){return x&(-x);}

原理就要涉及负数的编码了,负数都是正数的反码再加 \(1\) 得到的。

例如 \(12\) 的反码就是 \(0011\)(省略了前面若干位 \(1\)),再加 \(1\) 就是 \(0100\),再与原数进行按位与计算,就得到了 \(lowbit\)。

总而言之就是,二进制末尾有连续多少个 \(0\),反码就有连续多少个 \(1\),再加上一个 \(1\) 使其进位,最后与原数一样的就只有最后一个 \(1\) 及其后面的 \(0\)。

所以我们只需要把每个数都除以最小的 \(lowbit\) 就可以得到上述的情况。

我们再统计奇数数量,如果数量为偶,则有解;否则,无解。

那么,我们再确定 \(x=2\)(除后的,输出记得乘回去),问题就被转化为了有偶数个 \(1\),和奇数个 \(2\) 如何分配了。

只需要把两个 \(1\) 放在第一组,其他 \(1\) 平分,\(2\) 平分,然后把多出的一个 \(2\) 给第二组就好了。

AC 代码

#include<bits/stdc++.h>
using namespace std;
inline int lowbit(int x){return x&(-x);}
int n,a[100005],low=1000005,sum,flag,cnt1,cnt2=1;
int main()
{
	scanf("%d",&n);
	if(n%2==0)//先把n为偶的判断了
	{
		printf("1\n");
		for(int i=1;i<=n/2;++i) printf("01");
		exit(0);
	}
	for(int i=1;i<=n;++i) scanf("%d",&a[i]),low=min(low,lowbit(a[i]));//记录最小lowbit
	for(int i=1;i<=n;++i) a[i]/=low,sum+=a[i]%2;
	if(sum%2) printf("-1"),exit(0);
	printf("%d\n",2*low);//记得乘回去
	for(int i=1;i<=n;++i)
	{
		if(a[i]%2)
		{
			if(flag<2) flag++,a[i]=0;//flag记录在第一组单独放了多少个了
			else a[i]=cnt1,cnt1^=1;//然后就是平均分配了
		}
		else
		{
			a[i]=cnt2,cnt2^=1;//从第二组开始平均分配
		}
	}
	for(int i=1;i<=n;++i) printf("%d",a[i]);
}

标签:那么,gcd,奇数,int,lowbit,P9575,偶数,TAOI
From: https://www.cnblogs.com/One-JuRuo/p/17649522.html

相关文章

  • P9573 「TAOI-2」核心共振
    思路这道题最开始没发现数列必须是\(1,2,3,\cdots,n\),然后直接交了个输出\(n\)遍\(p\)的代码。我真的好蠢啊后面才发现这一点,于是开始思考,首先从\(p\)比较小的情况。如果\(p\)是\(1\)的话,那显然直接输出\(1,2,3,\cdots,n\)就好了。如果\(p\)是\(2\)的话,显然......
  • 「TAOI-2」Break Through the Barrier 题解
    前言:比赛前去做牙齿矫正,回来晚了10分钟……做比赛的运气全用在了一路绿灯上了(无语)。第二题切了两个半小时。决定写篇题解来抒发一下再记得愤怒愉悦之情。AC的想法很简单,就是表示出每一串连续的\(\texttt{T}\),其长度分别为\(l_1\liml_m\)。明显的,对于任何一个\(l_i\),在一......
  • 『STAOI』G - Round 3
    『STAOI』G-Round3因为在\(STAOI\)团里,所以赛时没打。\(T1\)luoguP9508『STA-R3』存在观察题意,手搓几组样例,易知符合题意的一组解形如\(a,b,b,c,b,b,……,z,(b),(b)\)。不会证明,可以参考下隔壁jijidawang的。时间复杂度\(O(n)\),可以通过本题。#include<bi......
  • 洛谷 P9221 「TAOI-1」Pentiment 题解
    Description给定\(n\timesm\)的矩阵,从第\(1\)行任意格子出发,每次向下、左、有走一步,有\(q\)个障碍不能经过,求走到第\(n\)行任意格子的方案。对于所有数据,\(1\leqn,m\leq10^9\),\(1\leqq\leq10^5\)。link:https://www.luogu.com.cn/problem/P9221Solution算法一考......
  • 『STAOI』G - Round 2 半个游记
    很刺激。2023.3.223:17第一次过审。2023.3.500:02第一次打回。原因是背锅人的链接又双叒叕挂错了(((2023.3.621:20第二次过审。2023.3.8邀请到国际著名设计师FoZwoK重新设计头图。这是base64。2023.3.8撤下比赛,决定打造rated。2023.3.13T4被偷走,拿去准备其它公......