牛客XBal月赛43总结

假期前的最后一次比赛,写完这篇就收拾收拾准备回家~
暂时都是做出来的题目,没做出来的等过两天再补题吧。

A:
在这里插入图片描述
在这里插入图片描述
由于可以包含自身,而最大因数必然是自身,故答案显然为n。

B:
在这里插入图片描述
看到数据范围,首先想到应该是有固定结论或单次不超过O(log(target))的解法。
首先,由于每次操作都要乘2,所以除非一开始就有一个瓶子的体积与目标相等,否则若目标为奇数,即不可完成。
否则,如果目标<max(a,b),假设a>b,那么只要从A瓶中倒掉 2 a − t a r g e t 2 \frac {2a-target}{2} 22atargetml即可达成目标。
否则,假设a>b,可以采取贪心的策略,先将B中的液体全部倒入A中,然后每次从A中向B中到1ml,直到2(a-1)≥target时多倒一些就可以。
代码如下:

if(t==m||t==n)    printf("0\n");
else if(t&1)    printf("-1\n");
else {
	if(m<n)    swap(m,n);
	if(t<m)    printf("1\n");
	else {
		int res=1;
		m=(m+n)*2;
		n=0;
		//不用计算最后一次倒了多少
		while(m<t) {
			m=(m-1)*2;
			n=(n+1)*2;
			res++;
		}
		printf("%d\n",res);
	}
}

D:
在这里插入图片描述
可以很自然地写出暴力解法:

for(int i=0; i<n; i++) {
	int now=a[i];
	for(int j=i; j<n; j++) {
		now|=a[j];
		if(now&1) {
			res++;
			//printf("[%d,%d]\n",i,j);
		}
	}
}

但这种方法的复杂度是远远不够的。
容易知道一个区间存在至少一个奇数是区间按位或结果为1的充要条件。考虑以下数据:

6
2 6 7 8 10 6

不难发现,奇数7“控制”的区间为:
[ i , j ] [i,j] [i,j] i ∈ [ 1 , 3 ] , j ∈ [ i , n ] i \in[1,3],j \in[i,n] i[1,3],j[i,n]
这样一来,它能对答案做出3 * (n-3+1)的贡献。推广到一般情况,位于i位置上的奇数能对答案做出i(n-i+1)的贡献。

但如果有多个奇数这个方法便会出现大量重复。一种解决方法是:让任何一个奇数都只能“控制”它后面和它前面直到上一个奇数之后的位置。那么我们只要记录上一个奇数出现的位置即可。

int lastOdd=-1;
for(int i=0; i<n; i++) {
	if(a[i]&1) {
		res+=(i-lastOdd)*(n-i);
		lastOdd=i;
	}
}

赛后补题1.17

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值