zoukankan      html  css  js  c++  java
  • 2019年9月15日晚间测试-T1

    T1

    题目描述:

      一开始你有一个数S,你可以通过两种操作改变这个值:

      1.给这个数加a

      2.给这个数乘b  

      问最少多少步操作可以使S变成T。

    输入格式:

      一行4个数,分别代表S,T,a,b。

    数据范围:

      1<S<T<1018

      1<a<1018

      2<b<1018

    这道题比较恶心了,看到1018的数据范围可能就会想到这是不是数学,然后搜刮脑子里那少的可怜的数学公式或定理(我就是这么做的,然后浪费了好长时间QAQ)

    不过我在手模样例的时候有了这么一个发现:

    好像所有的情况都能化简成最后的这个式子即:

    哦!天哪,这个wa太不吉利了(疯狂暗示)(˘•ω•˘)

    不过这样我们就可以贪心的解决这道题了

    while(s*b<t) s*=b,k++; 找到一个最大的k,使得bkS<T,然后 (T - bkS) / a找出W。

    这样数据就都全了,可是怎么求解最小步数呢?

    乘K次b肯定跑不了了,接下来要加多少次a呢?

    我们可以每次都 用W%b来获得最末尾项加a的次数,然后用 W / b来把倒数第二位的项变为最末尾的项,如下图:

    什么!你问如果Ci >b 怎么办?你可以想一想,如果它大于b,那你把它放到前一项里不是会更优吗?所以贪心的假定每一个C都小于b得到的就是优的结果。

    好,那咱们现在把题交上去。。。。。

    噫~好!我WA了!φ(≧ω≦*)♪ 

    现在咱们来考虑一下到底是哪出锅了。(*/ω\*)

    还是比较明显的,问题就出在这里 (T - bkS) / a不一定是个整数,也就是说,你找的这个最大的K其实不对,它没办法构成T。

    不过好在解决办法也很简单——把每个K都找一遍不就行了,就是b是最小的2,那K等于100时它也有1267650600228229401496703205376,这个数远超最大数据1018

    好!咱们再交一遍。。。。。。。

    噫~好!我又WA了( ゚∀゚)    ,究其原因无非就是1018太大了,很容易爆long long,这时候判断K就不能用 s*b<t 了,而是要改用 while( s<t / b)(我觉得其实应该加上等于号的,但是不加也过了)

    这次再交就没有问题了。( • ̀ω•́ )✧

    最后附上代码和注释:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 long long s,t,a,b;
     4 long long ans = 1e18+7;//先赋一个大值 方便取min 
     5 int main()
     6 {
     7     cin>>s>>t>>a>>b;//读入数据 
     8     
     9     if( (t-s)%a==0 ) //就是不乘b,纯用a加 
    10         ans = (t-s)/a;//如果能加出来就记录一下 
    11     
    12     long long k=0;//k就是指数 
    13     while( s<t/b )//防止爆longlong的优化 
    14     {
    15         k++;//寻找每个k 
    16         s*=b;//寻找每个k下的b(k)s 
    17         if((t-s)%a!=0) continue;//没办法用a凑出t,那这个k肯定就不对了 
    18         
    19         long long now = k;//方便处理 
    20         long long w = (t-s)/a;//找到 W 
    21         
    22         for(int i = 1; i<=k;i++)//循环多项式的每一项,找出常数C 
    23         {
    24             now += w%b;//加上这个常数C 
    25             w/=b;//把倒数第二位的项变成最后一项 
    26         }
    27         ans = min(ans,now+w);//在每种情况的k下寻找最小的步数
    28         //now+w是因为最后除完b会可能会剩下最高次项的常数 ,如果不剩下加个0也无所谓 
    29     }
    30     cout<<ans;//输出结果 
    31 }

    ( • ̀ω•́ )✧感谢大佬Accoty_AM的帮助

    (๑′ᴗ‵๑)I Lᵒᵛᵉᵧₒᵤ❤为美好的代码献上祝福

    (o°ω°o)CSP(NOOP)RP++

  • 相关阅读:
    Baskets of Gold Coins_暴力
    Inversion_树状数组***
    萌新的旅行-
    KI的斐波那契_DFS
    牛吃草_二分法
    See you~_树状数组
    Bellovin_树状数组
    Bubble Sort_树状数组
    [Python] numpy.ndarray.shape
    [Python] numpy.sum
  • 原文地址:https://www.cnblogs.com/Cainai-Liberty-Bird/p/11528244.html
Copyright © 2011-2022 走看看