SRM 478

開始5分前で参加決め込んだDIV2な人の挑戦…

  • 250 実装問題。キウイジュースを注いだりするそうです。
  • 500 10億7でたー。で、ちょっとよくわかりませんでしたが、今回は解けました。ふたつの移動が可換だということに気づいたところから、面倒なプロセスを踏んで回答。
  • 1000 2^25でいけるだろ、と思ったのですが、答えが合わない…思考停止。時間切れ。前回同様、動的計画法でやるそうです。正直分かってても構築できん!

もうちょっと頑張れば全完できたかもしれん。悔しい。

Result

250: Passed System Test
500: Passed System Test
1000: Compiled

250

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<set>
#include<map>
#include<cmath>
#include<complex>

using namespace std;

class KiwiJuiceEasy {
public:
  vector <int> thePouring(vector <int> capacities, vector <int> bottles, vector <int> fromId, vector <int> toId) {
    for(int m = 0; m < fromId.size(); ++m){
      int fr = bottles[ fromId[m] ];
      int to = bottles[ toId[m] ];
      int tocap = capacities[ toId[m] ];
      
      if( fr + to > tocap  ){
	bottles[ toId[m] ] = tocap;
	bottles[ fromId[m] ] = fr - (tocap - to);
      }else{
	bottles[ toId[m] ] += fr;
	bottles[ fromId[m] ] = 0;
      }
    }
    return bottles;
  }
};

500

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<set>
#include<map>
#include<cmath>
#include<complex>

#define MAX 300000
#define CARROT 1000000007
using namespace std;

class CarrotJumping {
public:
  long long int table[MAX+1];
  long long int f[MAX+1];
  void Make(){
    int tmp = 4;
    for(int n=2;n<=MAX;++n){
      table[n] = tmp % CARROT;
      tmp *= 2;
      tmp %= CARROT;
    }

    f[0]=1000;f[1]=1000;
    f[2]=1;f[3]=1;
    for(int n=4;n<=MAX;++n){
      f[n] = min( f[n-2]+1, f[n-3]+1 );
    }
  }
  
  int theJump(int init) {
    Make();
    long long int answer = MAX;
    vector< long long int > cands;
    for(int n = 2; n <= MAX; ++n){
      if( ( ((table[n]*init)%CARROT) + ((table[n]-1)%CARROT) ) % CARROT == 0 ){
	cands.push_back( n );
      }
    }
    for(int i = 0; i < cands.size(); ++i){
      answer = min( answer, f[ cands[i] ] );
    }
    if(answer > 100000 ) answer = -1;
    return (int)answer;
  }
};

解法メモ:
A(x) = 4x+3.
B(x) = 8x+7.
と置くと、A(B(A(B(B(A(x))))) など、このふたつからなる任意の移動 T(x) = 2nx + 2n-1, n = 2a + 3b であり、 a,b はそれぞれ T(x) を再現する際に A(x), B(x) を使用する回数となる。そこで、T(x) % 1000000007 == 0 となる n を列挙すれば、a+bが最小となるような n が答えとなる。