555555,能避开精度还是避开精度吧,,,,我们是弱菜。。
Poor Warehouse Keeper
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1672 Accepted Submission(s): 463





一个机器,只有两个按钮,上面的按钮表示数量,下面的表示总价(只显示整数部分)
开始的时候数量和总价都是1,单价为1,然后进行一些操作,让数量变成x,总价变成y,求得是最小操作次数。
如果按数量键,表示增加一个物品,单价不变,数量+1,那么总价=总价/数量*(数量+1),并且显示新的数量
如果按总价键,单价=(总价+1)/数量,那么总价=总价+1,并且显示总价的整数部分。
x很小y很大,暴力宽搜TLE了。
换个角度,求最小操作次数 换成 求最小合法单价的操作次数
因为最终得到了x数量,y的总价,对于一个单价tp,如果tp*x的整数部分==y那么这个单价就是可以的。
而最小操作次数一定是 得到最小合法单价的操作次数。
对于两种操作,按数量键并不会影响单价,按总价键会增加单价,而且增加单价的幅度是随着操作次数增多而下降的,按下数量键会是这个幅度下降的更多。
这样,一共要按下x-1次数量键,每次按数量键前尽量多的按总价键(保证该单价下的x个数量物品不会超过y元),最后会得到一个不超过目标单价(y/x)的最大单价z,该单价下的总价值为z*n如果z*n<y则还需要按下若干次总价键。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #include<map> 9 #include<set> 10 #include<string> 11 //#include<pair> 12 13 #define N 1005 14 #define M 1000005 15 #define mod 1000000007 16 #define inf 0x3f3f3f3f 17 //#define p 10000007 18 #define mod2 100000000 19 #define ll long long 20 #define LL long long 21 #define maxi(a,b) (a)>(b)? (a) : (b) 22 #define mini(a,b) (a)<(b)? (a) : (b) 23 24 using namespace std; 25 26 ll mul=3628800; 27 ll x,y; 28 ll ans; 29 ll tmi,tma; 30 ll dmi,dma; 31 ll dan; 32 ll num,tot; 33 34 void ini() 35 { 36 ans=0; 37 tmi=y*mul; 38 tma=(y+1)*mul; 39 dmi=tmi/x; 40 dma=tma/x; 41 num=1; 42 dan=mul; 43 tot=mul; 44 } 45 46 47 void solve() 48 { 49 ans=x-1; 50 ll k1,k2; 51 ll te; 52 if(dan>=dma){ 53 ans=-1;return; 54 } 55 for(num=1;num<=x;num++){ 56 te=mul/num; 57 if(dan>=dmi) break; 58 k1=(dmi-dan+te-1)/te; 59 k2=(dma-dan+te-1)/te; 60 // printf(" num=%I64d ans=%I64d dan=%I64d dmi=%I64d dma=%I64d te=%I64d k1=%I64d k2=%I64d\n", 61 // num,ans,dan,dmi,dma,te,k1,k2); 62 if(k1!=k2){ 63 ans+=k1; 64 dan+=k1*mul/num; 65 return; 66 } 67 else{ 68 dan+=(k1-1)*te; 69 ans+=(k1-1); 70 } 71 } 72 } 73 74 void out() 75 { 76 printf("%I64d\n",ans); 77 } 78 79 int main() 80 { 81 //freopen("data.in","r",stdin); 82 //freopen("data.out","w",stdout); 83 //scanf("%d",&T); 84 // for(int ccnt=1;ccnt<=T;ccnt++) 85 // while(T--) 86 while(scanf("%I64d%I64d",&x,&y)!=EOF) 87 { 88 //if(n==0 && k==0 ) break; 89 //printf("Case %d: ",ccnt); 90 ini(); 91 solve(); 92 out(); 93 } 94 95 return 0; 96 }