Hatena::Grouptopcoder

naoya_t@topcoder RSSフィード

2008-12-25

SRM399 Div1 Easy: AvoidingProduct

| 18:04 | SRM399 Div1 Easy: AvoidingProduct - naoya_t@topcoder を含むブックマーク はてなブックマーク - SRM399 Div1 Easy: AvoidingProduct - naoya_t@topcoder SRM399 Div1 Easy: AvoidingProduct - naoya_t@topcoder のブックマークコメント

走査範囲が狭くてシステムテスト落ち。書き直しの刑。(書き直しなのに6分17秒もかかったorz

class AvoidingProduct {
public:
  vector<int> getTriple(vector<int> a, int n) {
    int dmin = 1000;
    int uplim = 2000+a[0]+1; //2000あれば大丈夫っぽい
    
    set<int> s; tr(a,it) s.insert(*it); // NGリスト

    int amin=1001;
    for(int i=1;i<=1000;i++) {
      if (s.find(i)==s.end()) {amin=i;break;}
    }
    int am3=amin*amin*amin;
    if (am3>n) { vector<int> ans(3,amin); return ans; }

    vector<int> ans(3,-1);

    for(int x=1;x<=uplim;x++){
      if (s.find(x)!=s.end()) continue;
      for(int y=x;y<=uplim;y++){
        if (s.find(y)!=s.end()) continue;
        int xy = x*y;
        if(xy>uplim) break;
        for(int z=y;z<=uplim;z++){
          if (s.find(z)!=s.end()) continue;
          int xyz = xy * z;
          if(xyz>uplim) break;
          int d = abs(n-xyz);
          if (d<dmin) {
            dmin = d;
            ans[0]=x; ans[1]=y; ans[2]=z;
          }
        }
      }
    }
    return ans;
  }
};

SRM400 Div1 Easy: StrongPrimePower

| 18:04 | SRM400 Div1 Easy: StrongPrimePower - naoya_t@topcoder を含むブックマーク はてなブックマーク - SRM400 Div1 Easy: StrongPrimePower - naoya_t@topcoder SRM400 Div1 Easy: StrongPrimePower - naoya_t@topcoder のブックマークコメント

ある数が素数の累乗(2乗以上)かを調べる。pow()とか出てこなくて12分ぐらいかかった。(けれど一発で通った)

素数判定にはMiller-Rabinを使っている。


template <typename T> T expt(T x, int n) // x^n
{
  T y=1; for(int i=0;i<n;i++) y*=x; return y;
}

////
long long random(long long n)
{
  return (long long)rand() % n;
}
long long check_nontrivial_sqrt_1(long long m, long long a)
{
  long long r = (a * a) % m;
  return (1LL < a && a < m-1 && r == 1)? 0LL : r;
}
long long expmod(long long base, long long exp, long long m)
{
  if (exp == 0)
    return 1LL;
  else if (!(exp & 1))
    return check_nontrivial_sqrt_1(m,expmod(base,exp/2,m));
  else
    return (base*expmod(base,exp-1,m)) % m;
}
bool miller_rabin_test(long long n)
{
  return expmod((1LL+random(n-1)),n-1,n) == 1LL;
}
bool fast_prime(long long n, int times)
{
  if (n == 1) return false;
  if (n == 2) return true;
  else if (!(n & 1)) return false;
  
  for (int i=times; i>0; i--)
        if (!miller_rabin_test(n)) return false;
  return true;
}
////

class StrongPrimePower {
public:
  vector<int> baseAndExponent(string n) {
    long long n_ = 0; // 2-10^18=1000^6<2^60
    for(int i=0;i<n.length();i++) {n_*=10; n_+=n[i]-'0';}

    for (int q=59;q>=2;q--) {
      double q_ = 1.0 / q;
      double d_ = pow(n_,q_); long long p = (long long)(d_ + 0.0001);
      if (p == 0) continue;
      if (!fast_prime(p,3)) continue;
      if (expt(p,q)==n_) {
        vector<int> ans(2);
        ans[0]=p; ans[1]=q; return ans;
      }
    }
    vector<int> ans; return ans;
  }
};

SRM401 Div1 Easy: FIELDDiagrams

| 18:04 | SRM401 Div1 Easy: FIELDDiagrams - naoya_t@topcoder を含むブックマーク はてなブックマーク - SRM401 Div1 Easy: FIELDDiagrams - naoya_t@topcoder SRM401 Div1 Easy: FIELDDiagrams - naoya_t@topcoder のブックマークコメント

DP。単純な問題だが手間取っている。DPでいきなりコーディング空中分解しがち。

#define all(c)  (c).begin(),(c).end()
#define tr(c,i)  for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++)
#define rep(var,n)  for(int var=0;var<(n);var++)

class FIELDDiagrams {
public:
  int fo;
  vector<long long> memo;

  long long sub(int last,int fieldOrder){
    int ceil = min(last,fieldOrder);
    if (ceil == 0) { return 1;}

    int key=(ceil<<5)|fieldOrder;
    if (memo[key]>=0) return memo[key];
    long long count=1LL;
    for(int ai=ceil;ai>0;ai--){
      count += sub(ai,fieldOrder-1);
    }
    return memo[key] = count;
  }
  
  long long countDiagrams(int fieldOrder) {
    fo = fieldOrder;
    memo.resize(1024); fill(all(memo),-1);

    long long count = 0LL;
    for (int a1=fieldOrder;a1>0;a1--) {
      count += sub(a1, fieldOrder-1);
    }
    return count;
  }
};

SRM402 Div1 Easy: RandomSort

| 18:04 | SRM402 Div1 Easy: RandomSort - naoya_t@topcoder を含むブックマーク はてなブックマーク - SRM402 Div1 Easy: RandomSort - naoya_t@topcoder SRM402 Div1 Easy: RandomSort - naoya_t@topcoder のブックマークコメント

DP的問題。メモ化しないとTLE。状態の数はn^nあるが、vector<double>だとメモリ64MB制限に引っかかる。map<int,double>で必要なものだけメモ化するのが吉。

#define all(c)  (c).begin(),(c).end()
#define tr(c,i)  for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++)
#define rep(var,n)  for(int var=0;var<(n);var++)

template <typename T> T expt(T x, int n) // x^n
{
  T y=1; for(int i=0;i<n;i++) y*=x; return y;
}

class RandomSort {
  int n;
  vector<int> perm;
  //vector<double> memo;
  map<int,double> memo;

  int sig() {
    int s=0;
    tr(perm,it) s=s*n+(*it-1);
    return s;
  }
  double sw(){
    int key=sig();
    // if(memo[key]>=0) return memo[key];
    if(memo.find(key)!=memo.end()) return memo[key];

    set<pair<int,int> > s;
    rep(i,n){
      int p = perm[i];
      for(int j=i+1;j<n;j++){
        int q = perm[j];
        if (p>q) s.insert(make_pair(i,j));
      }
    }
    if (s.size() == 0) return memo[key] = 0;
    
    double cnt=0;
    tr(s,it){
      int i=it->first, j=it->second;
      int p=perm[i], q=perm[j];
      perm[i]=q; perm[j]=p;
      cnt += 1 + sw();
      perm[i]=p; perm[j]=q;
    }

    cnt /= s.size();
    return memo[key] = cnt;
  }
public:
  double getExpected(vector<int> permutation) {
    n=sz(permutation);
    perm = permutation;
    return sw();
  }
};

SRM403 Div1 Easy: TheLuckyNumbers

| 18:04 | SRM403 Div1 Easy: TheLuckyNumbers - naoya_t@topcoder を含むブックマーク はてなブックマーク - SRM403 Div1 Easy: TheLuckyNumbers - naoya_t@topcoder SRM403 Div1 Easy: TheLuckyNumbers - naoya_t@topcoder のブックマークコメント

10^9のループではTLEになるであろう数え上げ系。すこし手間取った(141.71points)。

こういうので200点以上とれるようになりたい。

int c(int n, int r)
{
  if (n == 0 || r == 0 || r == n) return 1;
  if (r > n-r) r = n-r;
  return n * c(n-1,r-1) / r;
}
int expt(int x,int n){
  int v=1; rep(i,n) v*=x; return v;
}

class TheLuckyNumbers {
public:
  int s_(int k,int n){
    int cnt=0;
    rep(i,1<<k){
      int u=0,m=1<<(k-1);
      rep(j,k){u*=10; u+=(i&m)?7:4; m>>=1;}
      if (n>=u) cnt++; else break;
    }
    return cnt;
  }
  int s(int k){
    return expt(2,k);
  }
  int lns(int n){
    if (n<4) return 0;
    if (n<7) return 1;
    if (n<44) return 2;
    if (n>777777777) n=777777777;

    int k=0,t=0,o=1;
    int n_=n;
    while(n_>0){ t=n_; n_/=10; o*=10; k++; }
    o = (o-1)/9;
    int o4=o*4, o7=o*7;
    int kt=k;
    int cnt=0;
    if (n<o7) {
      kt--;
      if (n>=o4) {
        cnt += s_(k,n);
      }
    }
    rep(i,kt) cnt+=s(i+1);
    return cnt;
  }
  int count(int a, int b) {
    return lns(b)-lns(a-1);
  }
};

SRM404 Div1 Easy: RevealTriangle

| 18:04 | SRM404 Div1 Easy: RevealTriangle - naoya_t@topcoder を含むブックマーク はてなブックマーク - SRM404 Div1 Easy: RevealTriangle - naoya_t@topcoder SRM404 Div1 Easy: RevealTriangle - naoya_t@topcoder のブックマークコメント

覆面算的な問題、と思ったけどそう難しくない。逆三角形の下から解いて行ける。

class RevealTriangle {
public:
  vector<string> calcTriangle(vector<string> questionMarkTriangle) {
    int rows=questionMarkTriangle.size(); //1-50

    vector<vector<int> > v(rows);
    rep(row,rows){
      v[row].resize(rows-row);
      rep(i,rows-row){
        int c = questionMarkTriangle[row][i]-'0';
        v[row][i] = (c < 0||9<c)?-1:c;
      }
    }

    for(int row=rows-1;row>=0;row--){
      int l=rows-row;
      string qmt= questionMarkTriangle[row];
      rep(z,l){
        rep(i,l) {
          if (v[row][i]<0) {
            if (i>0 && v[row][i-1]>=0) {
              v[row][i] = (10 + v[row+1][i-1] - v[row][i-1])%10;
            } else if (i+1<l && v[row][i+1]>=0) {
              v[row][i] = (10 + v[row+1][i] - v[row][i+1])%10;
            }
          }
        }
      }
    }
    vector<string> result(rows,"");
    rep(row,rows){
      stringstream ss;
      rep(i,rows-row) ss << (char)(48+v[row][i]);
      result[row] = ss.str();
    }
    return result;
  }
};

SRM405 Div1 Easy: RelativePath

| 18:04 | SRM405 Div1 Easy: RelativePath - naoya_t@topcoder を含むブックマーク はてなブックマーク - SRM405 Div1 Easy: RelativePath - naoya_t@topcoder SRM405 Div1 Easy: RelativePath - naoya_t@topcoder のブックマークコメント

カレントパスをもとに絶対パスから相対パスを求める問題。

class RelativePath {
public:
  string makeRelative(string path, string currentDir) {
    vector<string> vp = split(path,'/'), vcd = split(currentDir,'/');
    int lp=sz(vp), lcd=sz(vcd);
    int common=0;
    if(currentDir=="/") { lcd=1; common=0;}
    else
      for(int i=1;i<min(lp,lcd);i++){
        if(vp[i]!=vcd[i]) break;
        common++;
      }
    string dest=""; rep(i,lcd-1-common) dest+="../";
    for(int i=1+common;i<lp;i++) {dest+=vp[i];if(i<lp-1)dest+="/";}
    return dest;
  }
};

SRM406 Div1 Easy: SymmetricPie

| 18:04 | SRM406 Div1 Easy: SymmetricPie - naoya_t@topcoder を含むブックマーク はてなブックマーク - SRM406 Div1 Easy: SymmetricPie - naoya_t@topcoder SRM406 Div1 Easy: SymmetricPie - naoya_t@topcoder のブックマークコメント

next_permutationを使ってBrute Force

class SymmetricPie {
public:
  int getLines(vector<int> dogs) {
    int N=sz(dogs);
    sort(all(dogs));
    int maxcnt=0;
    while(1) {
      int cnt=0;
      vector<int> ac(N+1,0); ac[0]=0;
      for(int i=0;i<N;i++) ac[i+1]=ac[i]+dogs[i];
      for(int i=0;i<N;i++) {
        if (ac[i]<50){
          for(int j=i+1;j<=N;j++) {
            if (ac[j]-ac[i]==50) cnt++;
          }
        }
      }
      if (maxcnt<cnt) maxcnt=cnt;
      if (!next_permutation(all(dogs))) break;
    }
    return maxcnt;
  }
};

SRM407 Div1 Easy: CorporationSalary

| 18:04 | SRM407 Div1 Easy: CorporationSalary - naoya_t@topcoder を含むブックマーク はてなブックマーク - SRM407 Div1 Easy: CorporationSalary - naoya_t@topcoder SRM407 Div1 Easy: CorporationSalary - naoya_t@topcoder のブックマークコメント

再帰的に計算。メモ化。

class CorporationSalary {
  int N;
  vector<long long> salary;
  vector<vector<bool> > t;

  long long decide_salary(int id){
    if (salary[id] > 0) return salary[id];
    long long s=0LL;
    rep(j,N){
      if(t[id][j]) s+=decide_salary(j);
    }
    if (s==0LL) s=1LL;
    return salary[id] = s;
  }
public:
  long long totalSalary(vector<string> relations) {
    N = relations.size(); //1-50

    t.resize(N); tr(t,it) it->resize(N);
    rep(i,N) rep(j,N) t[i][j]=(relations[i][j]=='Y');

    salary.resize(N); tr(salary,it) *it=0;

    long long total=0LL;
    rep(i,N) total+=decide_salary(i);
    return total;
  }
};

SRM408 Div1 Easy: OlympicCandles

| 18:04 | SRM408 Div1 Easy: OlympicCandles - naoya_t@topcoder を含むブックマーク はてなブックマーク - SRM408 Div1 Easy: OlympicCandles - naoya_t@topcoder SRM408 Div1 Easy: OlympicCandles - naoya_t@topcoder のブックマークコメント

超簡単・・・なはずがSTLの操作でつまづく。

vector<int>から値が0の要素を削除するだけの簡単な仕事で。

tr(candles,it) if(!*it) candles.erase(it); →Segmentation Fault
remove(all(candles),0); →消えてないっぽい。なんで?

ゴミを消さないと駄目らしい。従って

class OlympicCandles {
public:
  int numberOfNights(vector<int> candles) {
    for(int nights=1;;nights++){
      sort(all(candles),greater<int>());
      if(candles.size() < nights) return nights-1;

      for(int i=0;i<nights;i++) candles[i]--;
      candles.erase(remove(all(candles),0),candles.end());
    }
  }
};