SRM 450 div1(practice)

21 篇文章 0 订阅

250pt:

      对普通nim游戏的改编,取石子的时候只能从前往后取,每次取非空的石子,不能取者为输。

     我是从后往前推的,注意当前数字如果>1,不管后面是必胜态还是必败态,肯定能调节成必胜态,如果=1,就身不由己了。。

500pt

  一开始,你有n个工厂,k个专家,每工作一轮,能获得n*k的gold,购买一个工厂或者一个专家需要price的gold,你想要获得的gold是target,当你具备足够的钱买一个专家或者工厂的时候,你可以买任意多个专家或工厂。问你最小需要几轮才能获得target的gold。

 这是一个 看似难写,实则更难写的模拟题。。

  注意到n k肯定是越接近越好,还有当前如果要买一个专家或者工厂,那肯定是花所有的钱去买(n,k肯定是越早增大越好)。因为下一轮就赚回来了。还有就是假设当前的钱>=price了,就需要先判断一下是不是要买工厂或者专家了,因为有可能凭借当前的nk,很快就能到达target了。

 代码写的比较渣,错了很多遍

#include <cstdio>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <sstream>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <bitset>
#include <algorithm>
using namespace std;
typedef long long lld;
class StrongEconomy {
public:
    lld ABS(lld a)
    {
        if(a > 0) return a;
        return -a;
    }
    void get(lld &n,lld &k,lld &tim) {
        if(tim >= ABS(n-k) )
        {
            lld tn = n , tk = k;
            n = (tn+tk+tim) / 2;
            k = (tn+tk+tim+1) / 2;
        }
        else
        {
            if(n>k) k+=tim; else n+=tim;
        }
    }
    lld gao(lld n,lld k,lld price,lld target,lld earn) {
        lld tim = earn / price;
        earn -= tim * price;
        get(n,k,tim);
        lld tmp = mul(n,k);
        if(tmp == -1) return tmp;
        lld ans = (target - earn)/tmp;
        if((target-earn)%tmp) ans ++;
        return ans;
    }
    lld mul(lld a,lld b) {
        lld ans = 0;
        bool flag = false;
        for(int i=0; i<50; i++) {
            // cout<<ans<<endl;
            if(b&(1LL<<i)) {
                if(flag) return -1;
                ans = ans + a;
                if(ans > 1000000000000LL) return -1;
            }
            a = a + a;
            if(a > 1000000000000LL) flag = true;
        }
        return ans;
    }
    lld earn(lld n, lld k, lld price, lld target)  {
        if(mul(n,k) == -1) return 1;
        lld round = 0;
        lld earn = 0;
        while(true) {
            lld tmp = mul(n,k);  if(tmp == -1) return round ;
            //  cout<<earn<<endl;
            if(earn >= target) break;
            if(earn >= price) {
                lld tmp = mul(n,k);
                lld tmp1 = (target - earn) / tmp ;
                if((target-earn)%tmp) tmp1++;
                lld tmp2 = gao(n,k,price,target,earn);
            //    cout<<tmp1<<" "<<tmp2<<endl;
                if(tmp1 < tmp2 ) {
                    round += tmp1;
                    break;
                } else {
                    lld tim = earn / price;
                    if(tmp2 == -1) return round + 1;
                    earn -= tim * price;
                  //  cout<<"pre"<<" "<<n<<" "<<k<<" "<<tim<<endl;
                    get(n,k,tim);
                   // cout<<n<<" "<<k<<" "<<earn<<endl;
                }
            }
            else if(price < target){
                lld tmp = n * k;
                lld t = (price-earn)/tmp;
                if((price-earn)%tmp) t++;
                round += t;
                earn += t * n * k;
                cout<<"earn"<<" "<<earn<<endl;
            } else {
                lld tmp = n * k;
                lld t = (target-earn)/tmp;
                if((target-earn)%tmp) t++;
                round += t;
                earn += t * n * k;
            }
          //  cout<<n<<" "<<k<<endl;
        }
        return round;

    }

// BEGIN CUT HERE
public:
    void run_test(int Case) {
        if ((Case == -1) || (Case == 1)) test_case_1();
    }
private:
    template <typename T> string print_array(const vector<T> &V) {
        ostringstream os;
        os << "{ ";
        for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\",";
        os << " }";
        return os.str();
    }
    void verify_case(int Case, const lld &Expected, const lld &Received) {
        cerr << "Test Case #" << Case << "...";
        if (Expected == Received) cerr << "PASSED" << endl;
        else {
            cerr << "FAILED" << endl;
            cerr << "\tExpected: \"" << Expected << '\"' << endl;
            cerr << "\tReceived: \"" << Received << '\"' << endl;
        }
    }
    //void test_case_0() { lld Arg0 = 4294967297LL; lld Arg1 = 4294967297LL; lld Arg2 = 1000000000000LL; lld Arg3 = 100000000000LL; lld Arg4 = 1LL; verify_case(0, Arg4, earn(Arg0, Arg1, Arg2, Arg3)); }
    void test_case_1() {
        lld Arg0 = 3LL;
        lld Arg1 = 2LL;
        lld Arg2 = 1000000000000LL;
        lld Arg3 = 222LL;
        lld Arg4 = 37LL;
        verify_case(1, Arg4, earn(Arg0, Arg1, Arg2, Arg3));
    }
//	void test_case_2() { lld Arg0 = 1LL; lld Arg1 = 1LL; lld Arg2 = 500000LL; lld Arg3 = 1000002LL; lld Arg4 = 1000001LL; verify_case(2, Arg4, earn(Arg0, Arg1, Arg2, Arg3)); }
    //void test_case_3() { lld Arg0 = 5LL; lld Arg1 = 4LL; lld Arg2 = 15LL; lld Arg3 = 100LL; lld Arg4 = 5LL; verify_case(3, Arg4, earn(Arg0, Arg1, Arg2, Arg3)); }

// END CUT HERE

};

// BEGIN CUT HERE
int main() {
    StrongEconomy ___test;
    ___test.run_test(-1);
}
// END CUT HERE

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值