#include <stdio.h>
int main()
{
puts("转载请注明出处[vmurder]谢谢");
puts("网址:blog.csdn.net/vmurder/article/details/43450731");
}
题意:
初始状态为:1个物品,总价为1。
目标状态为:x个物品,总价为y。
操作A:变为x+1,y+y/x。(y不取整)
操作B:变为x, y+1
问最少多少步可以达成条件?(最后操作结束后对y取整)
如果不行输出-1。
题解:
先说"-1"
首先如果x<=y,,那么我们可以先一直做操作一,使得状态变为(x,x),然后暴力给y+1
一定可以达成,所以只需要在x>y时输出"-1"就好了。
然后是x<=y的情况。
我们考虑操作A的次数是固定的~~
那么就应该让操作B尽量少,也就是让单价尽量快地到达要求。
那么就应该尽早采取操作B。
于是就有了下述策略:
计算当前单价为a,目标单价为b,然后此时一次操作B能给单价增加多少~
然后从小到大枚举当前数量,尽可能多地使用操作B。
呃,这样的话样例3输出12~~~
所以我们就应该考虑只要采取了k次操作B以后总价不会超过目标价格+1-eps就好了~~
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 10
#define eps 1e-9
using namespace std;
int main()
{
freopen("test.in","r",stdin);
int i,j,k;
double x,y;
while(scanf("%lf%lf",&x,&y)!=EOF)
{
if(x-y>eps)
{
puts("-1");
continue;
}
int ans=(int)(x+eps-1);
double now=1.0;
double sum=0.0;
for(i=1;i<=(int)(x+eps);i++)
{
sum=now*i;
k=(int)(y/x*i-sum);
ans+=k;
now+=(double)k/i;
if((sum+k+1)/i*x-y<1.0)
{
now+=1.0/i;
ans++;
}
}
if(now<(double)y/x)ans++;
printf("%d\n",ans);
}
return 0;
}