#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; }
时间: 2024-10-10 03:41:40