易得(2²+2³+…2k)=2(k+1)-2
分三类情况讨论
L>2k+1-2 即使所有梯子相加,长度也不够 No
L==2k+1-2 Yes 最长的梯子明显是2k
L<2k+1-2 需要重点讨论:
(L奇偶可以讨论,但没必要)
先看例子:
3 10
即 长度分别为 2,4,8的梯子,如何相加变为10;
思路是:
10减去最大的数2³ (2的3次方)=> 10-8=2
2 减去第二大的数2²(2的2次方)=> 2-4=-2<0 此时小于0 依旧用2
2 减去第三大的数2(2的1次方)=> 2-2=0
利用2,8的梯子即可相加为10
又自己举了几个例子:
3 6
即 长度分别为 2,4,8的梯子,如何相加变为6;
思路是:
6减去最大的数2³ (2的3次方) => 6-8=-2 此时小于0 依旧用6
6减去第二大的数2²(2的2次方)=> 6-4=2
2减去第三大的数2(2的1次方)=> 2-2=0
利用2,8的梯子即可相加为10
3 11
即 长度分别为 2,4,8的梯子,如何相加变为11;
思路是:
11减去最大的数2³ (2的3次方) => 11-8=3
3减去第二大的数2²(2的2次方)=> 3-4=-1 此时小于0 依旧用3
3减去第三大的数2(2的1次方)=> 3-2=1
1!=0,利用2,4,8的梯子不可能相加为11
(因此不需要讨论奇偶,因为一个奇数减去偶数不可能得到偶数0)
由此可得 用L依次减去2k,2k-1,2k-2,2k…2
当相减小于0时,L返回相减前的L值
当k=1时结束循环
结束循环时 判断L的值是否为0
若不为0 N0
若为0 Yes,输出 小于L的 最大的2的幂
注意pow函数为double型,需要(long long int)
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main()
{
int k,K;
long long int L,l,ans;
scanf("%d %lld",&k,&L);
K=k,l=L; //储存k,L
if(L>pow(2,k+1)-2) printf("No");
else if(L==(long long int)pow(2,k+1)-2)
printf("Yes\n%lld",(long long int)pow(k,2));
else{
do{
if(L-(long long int)pow(2,k)==0){
L=0;break;}
if(L-(long long int)pow(2,k)>0)
L=L-(long long int)pow(2,k);
k--;
}while(k!=0);
if(L==0){
printf("Yes\n");
if(l>=(long long int)pow(2,K))
printf("%lld",(long long int)pow(2,K));
else {
while(1){
if((long long int)pow(2,K)<l){
printf("%lld",(long long int)pow(2,K));
break;}
K--;}
}
}
else printf("No");
}
return 0;
}