codeforces1080D 2000分数学

题目传送门

题意:

有一个大小是2^n * 2^n的正方形,让你进行k次操作。

有一种操作:选择一个a*a的正方形,切割成4个大小为\frac{a}{2} * \frac{a}{2}的正方形,且不改变正方形的位置,即只画出分割线,看上去还是一个大小是2^n * 2^n的正方形。a\geqslant 2 并且 a是偶数。

询问你是否能从左下角走到右上角,只能向上走和向右走,并且经过的正方形大小相同。

如果可以,设这些正方形的边长为x,输出log_2(x)

数据范围:1\leqslant n\leqslant 10^91\leqslant k\leqslant 10^{18}

题解:

需要发现:当n\geqslant 32时,一定有解,且输出n-1。画画图就知道了。

n\leqslant 31时,任何合理的计算都不会爆long \; long,可以放心的计算。

分析n\leqslant 31的情况:

枚举路径上的正方形边长,可以发现以下等式成立时有解。

\Sigma _{j=1}^{i}(2^j-1)\leqslant k\leqslant \Sigma _{j=1}^{n}2^{(j-1)*2}-\Sigma _{j=1}^{n-i}2^{(j-1)*2}*(2^{i+1}-1) \; (1 \leqslant i \leqslant n)

n-i是路径上的正方形边长。

扫描二维码关注公众号,回复: 9153243 查看本文章

\Sigma _{j=1}^{i}(2^j-1)是路径上的正方形所需切割次数。

\Sigma _{j=1}^{n}2^{(j-1)*2}是切割整个正方形所需切割次数。

\Sigma _{j=1}^{n-i}2^{(j-1)*2}*(2^{i+1}-1)是将路径上的正方形切割至无法切割的状态所需的切割次数。

感受:

这道题第一次看到时想了一个小时做不出来。

现在第二次看到时想了两个小时想吐了,然后看了看题解的第一行(从知乎学习的看题解方法,看一行题解接着思考,思考不出再看一行,尽量多的思考),发现和自己想的思路差不多,于是硬着头皮接着搞出来了。

标签写着math的题我是真的不会啊。。。。。。

代码:

#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
ll qpow(ll x , ll y)
{
	ll ans = 1 ;
	while(y)
	{
		if(y & 1)  ans *= x ;
		x *= x , y >>= 1 ;
	}
	return ans ;
}
ll sum(ll x)
{
   ll ans = 0 ;
   for(ll i = 1 ; i <= x ; i ++)
     ans += qpow(2 , (i - 1) * 2) ;
   return ans ;	
} 
ll cal(ll x)
{
	ll ans = 0 ;
	for(ll i = 1 ; i <= x ; i ++)  ans += qpow(2 , i) - 1 ;
	return ans ; 
}
int main()
{
	int t ;
	scanf("%d" , &t) ;
	while(t --)
	{
		ll n , k ;
		bool flag = 0 ;
		int temp ;
		scanf("%lld%lld" , &n , &k) ;
		if(n >= 32){printf("YES %lld\n" , n - 1) ; continue ;}
		ll sum1 = sum(n) ;
	    for(ll i = 1 ; i <= n ; i ++)
	    {
	    	ll s = cal(i) ;
	    	ll t = sum(n - i) * (qpow(2 , i + 1) - 1) ;
	    	if(s <= k && k <= sum1 - t){flag = 1 , temp = n - i ; break ;}
		}
		if(flag)  printf("YES %d\n" , temp) ;
	 	else  printf("NO\n") ;  
	}
	return 0 ;
}
发布了215 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Irving0323/article/details/104091218
今日推荐