C-merのブログ

ザ・雑記

SRM 500 Div 1 - Problem 250 MafiaGame

問題
SRM 500 Div 1 - Problem 250 MafiaGame
TopCoder Statistics - Problem Statement

使用言語
C++

方針
・最も投票された人にのみ注目
・N人の人が残る候補者にどう投票するかでループ

所感
・問題文理解できなかったり,スペルわからなくなったり,英弱の極みという感じだった.
・複雑に考えちゃいけない問題

コード

vector<int> vote(555, 0);

class MafiaGame {
    public:
    double probabilityToLose(int N, vector<int> decisions) {
      int size = decisions.size();
      for (size_t i = 0; i < size; i++) {
        vote[decisions[i]]++;
      }

      //最も投票された回数
      int maxvote = *max_element(vote.begin(), vote.end());
      //最も投票された人の人数
      int maxnum = count(vote.begin(), vote.end(), maxvote);

      //最も投票された人でも1票ということは,全員1票で無限ループ
      if (maxvote == 1 && N != 1) return 0.0;
      //単独で最多投票獲得数ならばその人が敗者決定
      if (maxnum == 1) return 1.0;

      //ここで候補を絞る
      //N票しか存在しないので,候補者がmaxnum以上になることはない
      //確実に入れる人の数は同じなので,全員ランダムとみなして問題ない
      //一人になったら終了
      int candidate = maxnum;
      while (candidate != 1) {
        //次の投票数が最多の人の人数を計算
        candidate = N % candidate;
        //(mod 0)==投票数が最多の人の人数が変化しない==無限ループ
        if (candidate == 0) return 0.0;
      }

      //maxnum人の中誰が候補者になっておかしくなかった.
        return 1.0 / maxnum;
    }
};

主に要約など参考:
Top Coder Single Round Match 500 Div1 - 練習帳 - TopCoder部

ABC097-C(12問目)

問題
AtCoder Beginner Contest 097 C - K-th Substring
C: K-th Substring - AtCoder Beginner Contest 097 | AtCoder


使用言語
C++

方針
・k文字以下の文字列作りまくる
→木にぶち込む
→k番目出力

所感
・setディスられてたの見たけど,重複可なの逆に便利

コード

int main()
{
  string s;
  int K;
  set<string> S;

  cin>>s>>K;

  int size = s.length();

  for (int i = 0; i < size; i++) {
    string tmp;
    for (int j = 0; j < 5 && j + i < size; j++) { //多分ここ5じゃなくてkでもいける
      tmp = s.substr(i, j+1);
      S.insert(tmp);
      //cout<<tmp<<S.size()<<endl;
    }
  }


  set<string>::iterator itr = S.begin();
  for (int i = 0; i < K - 1; i++) itr++;

  cout<<(*itr)<<endl;

  return 0;
}

三年目の初学者(11問目)

問題
Topcoder Single Round Match 620 Round 1 - Division I, Level One
TopCoder Statistics - Problem Statement

使用言語
C++

方針
大きいところから、一個ずつ値を減らしていく。
(X, Y) -> (X-Y, Y) (X >= Y の時)

・一致したら終了(これ以下の値の数字の組も題意を満たすかもしれないが、x+yの最大値を求める問題なので、これで十分)


所感
・0になった時の処理が少し面倒くさいです。
・文字通りの逆転の発想。

コード

class PairGame {
    public:
    int maxSum(int a, int b, int c, int d) {
      while (a != c || b != d) {
        if ((a == 0 || b == 0) && (c == 0 || d == 0)) break;
        int maxab, maxcd;

        if (a == 0 || b == 0) maxab = 0;
        else maxab = max(a, b);
        if (c == 0 || d == 0) maxcd = 0;
        else maxcd = max(c, d);

        if (maxab >= maxcd) {
          if (a >= b) a -= b;
          else b -= a;
        } else {
          if (c >= d) c -= d;
          else d -= c;
        }
      }
        return a == c && b == d ? a + b : -1;
    }
};

三年目の初学者(10問目)

問題
Topcoder Single Round Match 619 Round 1 - Division I, Level One
TopCoder Statistics - Problem Statement

使用言語
C++

方針
まず、
1発でLOSEする状態を考える。初期で
{n1, n2} (数字2つ以下)
{1, 1, 1, ... , 1} (すべて1)
となるとき。

重要なのは「分割」するということなので、各numberにおいて重要なのは、2以上であるかどうか。
分割したものは、また別のnumberに加えるということなので、
{n, 1, 1, ... , 1} (n>=2)
というデータセットだとしても、次の操作で
{0, m1, m2, 1, ... , 1} (mi>=2)
となり、分割が続けられる。

WINする状況とは、Shinyの回で
{n1, n2, n3, 0, 0, ... , 0}
となる状況である。

{n1, n2, n3, n4, 0, 0, ... , 0} ではLOSE
{n1, n2, n3, n4, n5, 0, 0, ... , 0} ではWIN
.
.
.
(n>=1)

と、帰納的に奇数でWIN、偶数でLOSEであるとわかる。
って感じ。


所感
・頭やわらかゲー
・紙に書くの大切

コード

class SplitStoneGame {
    public:
    string winOrLose(vector<int> number) {
      if (number.size() <= 2 || number.size() % 2 == 0 ||
      number[*max_element(number.begin(), number.end())] == 1)
        return "LOSE";
      else return "WIN";
    }
};

三年目の初学者(9問目)

問題
AtCoder Beginner Contest 092 C - Traveling Plan
C: Traveling Plan - AtCoder Beginner Contest 092 | AtCoder


使用言語
C++

方針
・本来の値段をまず求めて、そこから値段を増減させる。
・計算量的にもこれがベスト

所感
・すぐに解きたい問題だったが、時間かかった
・添字大事。

コード

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define REP(i,b) FOR(i,0,b)
#define INF 1e9

int solve(int a[], int all_payment, int i)
{
  int ans = all_payment;

  ans += max(a[i-1], a[i+1]) - min(a[i-1], a[i+1]);
  ans -= max(a[i-1], a[i]) - min(a[i-1], a[i]);
  ans -= max(a[i], a[i+1]) - min(a[i], a[i+1]);

  return ans;
}

int main()
{
  int n, tmp, all_payment = 0;
  cin>>n;

  int a[n+2];
  a[0] = 0; a[n+1] = 0;
  FOR(i,1,n+1) {
    cin>>a[i];
  }

  REP(i,n+1) all_payment += max(a[i], a[i+1]) - min(a[i], a[i+1]);

  FOR(i,1,n+1) {
    cout<<solve(a, all_payment, i)<<endl;
  }

  return 0;
}

三年目の初学者(8問目)

問題
AtCoder Beginner Contest 093 D - Worst Case
D - Worst Case

使用言語
C++

方針
・100マス計算の表みたいな感じで行けるものだと思っていたが、細かいところができない。
・解説(https://img.atcoder.jp/arc094/editorial.pdf)を参考にした。下の通りに考えると判りやすい。(丸が最大となるときの候補の一つ)

f:id:C-mer:20180408200537j:plain
f:id:C-mer:20180408201622j:plain
f:id:C-mer:20180408201712j:plain

所感
・簡単そうに見えて難しそうなやつだと思ったら、やっぱりそうだった。
・実装はクソ楽。
・結構力作の解説のつもり。
・桁落ち、負の処理、根号の処理を気をつけたい。

コード

#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
using namespace std;
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define REP(i,b) FOR(i,0,b)
#define INF 1e9

typedef long long ll;
typedef unsigned long long ull;

void solve(ll a, ll b)
{
  if (a > b) swap(a, b);
  //常に a <= b

  if (b - a <= 1) {
    cout<<2 * (a - 1)<<endl;
  } else {
    ll c = (int) sqrt(a * b);
    if (c * c == a * b) c--;

    if (c * (c + 1) >= a * b) {
      cout<<2 * (c - 1)<<endl;
    } else {
      cout<<2 * c - 1<<endl;
    }
  }
}


int main(){
  int q;
  cin>>q;

  ll a[q], b[q];
  REP(i,q) cin>>a[i]>>b[i];

  REP(i,q) solve(a[i], b[i]);

  return 0;
}

三年目の初学者(7問目)

問題
topcoder SRM 602 div1 easy
TopCoder Statistics - Problem Statement


使用言語
C++

方針
・全探索
(・dp)

所感
・いけるもんだと思っていた。実行するまでは

問題点と解決案(解決してない)
・O(2^n)で大変
・一部ケースでTLEになったため、残りの全てのコンテストで勝ったとしても2200を超えない(brown coderにならない)場合はすぐに0を返すようにした。
・実行時間が少し減少したが、一部TLEのまま
・できたら追記します

コード

//status: true->brown, false->ciel
int cc (int rate, int i, vector<int> D, int size, bool status, vector<int> dp)
{
  if (i == size) return 0;

  if (status) {
    return (rate - D[i] < 2200)
            ? cc(rate - min(rate, D[i]), i+1, D, size, false, dp) + 1 : -INF;
  } else {
    if (rate + dp[i] < 2200) return 0;

    int r = rate + D[i];
    bool status_p = (r >= 2200);
    return max(cc(r, i+1, D, size, status_p, dp) + (int) status_p,
            cc(rate - min(rate, D[i]), i+1, D, size, false, dp));
  }
}

class TypoCoderDiv1 {
    public:
    int getmax(vector<int> D, int X) {
      int size = D.size();

      vector<int> dp(51, 0);
      for (int i = size - 1; i >= 0; i--) {
        dp[i] = dp[i+1] + D[i];
      }

        return cc(X, 0, D, size, X >= 2200, dp);
    }
};