FZU2147 A-B Game(贪心)

来源:互联网 发布:java影院售票系统 编辑:程序博客网 时间:2024/06/18 09:56

题意

       输入A、B(B<A)。A每次可以进行一次变换:A = A - (A % x) ,其中1≤x≤A-1。问最少经过多少次变换,A的值小于等于B。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

分析

       如果A%x的最大值与A成正比,那么这就是一道贪心题,每步都取让A%x值为最大的x即可。即每一步都让A减去尽可能大的值是这道题的解题思路。

       现在分析A%x的性质,最优解x(让A减去的值最大),其实就是比A的一半更大一点点的整数,即


       (以下我的证明方法仅供参考,关键是读者自己想明白其中的道理。)

       为什么呢?如下图中的彩色线段,我们把数A理解成长度为A的线段。比中点稍大的整数就是图中绿色的点,余数相当于绿点右边红色线段的长度,长度为

       如果取绿点右边的某个整数点y,则余数是点y至终点的线段长度,显然会比原来的短。

       如果取绿点左边的某个整数点z。那么有两种情况:

  1. 一种是中点存在,如图中的黄点,此时A%z为0,必然不是最优解。
  2. 另一种情况是z为中点左边的某个点(图中的灰点),则必然有 (想一想为什么),又 ,所以



       再简单的分析,知公式中的实际就是变化后A的值,故代码很简单:

#include <cstdio>#include <iostream>using namespace std;typedef long long LL;int main() {    int T;    scanf("%d", &T);    for (int kase = 1; kase <= T; kase++) {        printf("Case %d: ", kase);        LL a, b, cnt = 0;        cin >> a >> b;        while (a > b) {            a = a/2 + 1;            cnt++;        }        printf("%d\n", cnt);    }    return 0;}

0 0
原创粉丝点击