ferinの競プロ帳

競プロについてのメモ

SRM664 div1 easy BearPlays

考えたこと

  • 操作回数KでO(K)はできないならどうせ周期性という気持ちになる
  • 周期性で O(min(A+B, K)) くらいにはなりそうという気持ちになるが足りない
  • 適当に実験したら実は周期が短いのがわかるのでは?と思い実験する
  • 3*10^6回実行しても周期性がないのがある
  • 周期が長すぎて周期性つかえない気持ちになってくる
    -----解説を見た-----
  • 何もわからないので解説を見る
  • 小さい方を2倍するとか考えずにとりあえずAを2倍する処理ということにする
  • 大きい方を2倍したとしても mod A+B を取るとこれは問題の操作に一致する
  • したがってK回操作を行ったときAは ret = A*2^K mod A+B になる
  • min(ret, A+B-ret) が答え

どうせ周期性だろうと思ったら違った…
大きい方を2倍したらどうなるか考える発想がなかった
mod A+Bを取るのが全く思いつかなかった

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<ll> VL;
typedef vector<VL> VVL;
typedef pair<int, int> PII;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()
#define IN(a, b, x) (a<=x&&x<b)
#define MP make_pair
#define PB push_back
const int INF = (1LL<<30);
const ll LLINF = (1LL<<60);
const double PI = 3.14159265359;
const double EPS = 1e-12;
int MOD = 1000000007;
//#define int ll

template <typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }

int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};

//二分累乗法 xのe乗
ll binpow(ll x, ll e) {
  ll a = 1, p = x;
  while(e > 0) {
    if(e%2 == 0) {p = (p*p) % MOD; e /= 2;}
    else {a = (a*p) % MOD; e--;}
  }
  return a % MOD;
}

class BearPlays {
   public:
   int pileSize(int A, int B, int K)
  {
    MOD = A+B;
    int ret = A*binpow(2,K)%MOD;
    return min(ret, A+B-ret);
  }
};