F. Fair Distribution

F. Fair Distribution

18界浙江省赛

1)题目大意:

有n个机器人和m个能量棒,每次操作可以杀掉一个机器人或者增加一个能量棒。问最少几次操作可以使得n'个机器人平分m'个能量棒。

2)思路:

暴力整数分块

暴力思路:枚举1到n每一个机器人的情况,算出第一个比b大的i的倍数,取min。

ll getceil(ll x , ll y){
	return x / y + (x % y ? 1 : 0) ;
}

ll solve(){

	ll a , b ;
	cin >> a >> b ;
	
	if(b % a == 0) return 0 ;
	if(a > b) return a - b ;
	ll ans = INF ;
	
	for(int i = 0 ; a - i > 0 ; i ++ ){//i是操作次数
		ll opBar = getceil(b , a - i) * (a - i) - b ;
		ans = min(ans , i + opBar) ;
	}
	return ans ;
}

枚举1到n一定会超时,所以采用整数分块

对于整除,x/y的答案是有块状的性质的(ceil和floor都有),所以我们对于某一块区间里的除数不用全部去操作,而是可以直接用端点来做。

ll getceil(ll x , ll y){//x/y向上取整的公式 
	return (x + y - 1) / y ;
}

ll solve(){

	ll a , b ;
	cin >> a >> b ;
	
	if(b % a == 0) return 0 ;
	if(a >= b) return a - b ;
	
	ll ans = INF ;

	for(ll l = 1 , r ; l <= a ; l = r + 1){ 
		r = (b - 1) / ((b  - 1) / l) ;//向下取整区间分块
		ans = min(ans , getceil(b , l) * l - b + a - l) ;
	}
	
	return ans ;
}
3)扩展和总结:

需要枚举n/i的答案时就可以用整数分块

复杂度2根n

向下取整的分块:

for (ll l = 1, r; l <= m; l = r + 1) {
    r = n / (n / l);  
}

向上取整的分块:

for(ll l = 1 , r ; l <= a ; l = r + 1){ 
		r = (b - 1) / ((b  - 1) / l) ;//向下取整区间分块
	}

原文链接: https://www.cnblogs.com/tyriis/p/15789157.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    F. Fair Distribution

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/184855

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月12日 上午10:49
下一篇 2023年2月12日 上午10:49

相关推荐