CF1864C Divisor Chain

去洛谷看我的博客

思路

刚拿到题,想了一些方法但都被推翻了,在这里列举出来,并给出反例:

  • 每次减去最小的因数,反例: 1024 1024 1024 等形如 a k a^k ak 的数,每次都会减去 a a a 导致 a a a 的出现次数超过 2 2 2 次。

  • 每次减去大于等于 x \sqrt x x 的因子, x x x 为目前的数,并特判指数的情况,反例: 35 35 35 等由两个质数相乘的数,会减去多次较大的质数,导致出现次数超 2 2 2 次。

  • 记忆化搜索,没反例,但是时间复杂度会超。

在经过多次尝试后,我终于想到了一点,如果 x x x 是形如 2 k 2^k 2k 的数,可以每次减去 x 2 \frac x 2 2x 直到变为 1 1 1

那么,我们尝试把给定的数变为 2 k 2^k 2k 的形式。

发现给定的数离 2 k 2^k 2k 的差距就只是二进制下除了最高位的 1 1 1

所以可以先每次减去 lowbit ⁡ ( x ) \operatorname{lowbit}(x) lowbit(x),直到 x x x 2 k 2^k 2k,然后再每次减去 x 2 \frac x 2 2x

发现前半部分最多减去了一次 2 l 2^l 2l 其中 0 ≤ l < k 0\le l <k 0l<k

然后后半部分会减去 2 m 2^m 2m 其中 0 ≤ m < k 0\le m <k 0m<k 各一次。

所以不会超过 2 2 2 次的限制。

AC code

#include<bits/stdc++.h>
using namespace std;
inline int lowbit(int x){return x&(-x);}
int T,n,ans[1005],cnt,nn;
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n),cnt=0,nn=n;
		while(n&(n-1))//判断是否变为2^k
		{
			ans[++cnt]=lowbit(n),n-=lowbit(n);//记录操作
		}
		while(n>1) ans[++cnt]=n/2,n/=2;//每次减去n/2
		printf("%d\n",cnt+1);//操作cnt次,共cnt+1个数
		for(int i=1;i<=cnt;++i)
		{
			printf("%d ",nn),nn-=ans[i];
		}
		printf("%d\n",nn);
	}
	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值