Hatena::Grouptopcoder

naoya_t@topcoder RSSフィード

2009-01-17

SRM365 Div1 Easy: PointsOnCircle

| 12:52 | SRM365 Div1 Easy: PointsOnCircle - naoya_t@topcoder を含むブックマーク はてなブックマーク - SRM365 Div1 Easy: PointsOnCircle - naoya_t@topcoder SRM365 Div1 Easy: PointsOnCircle - naoya_t@topcoder のブックマークコメント

300点問題・・・普通にやってたらTLE

typedef long long ll;
#define sz(a)  int((a).size())
#define pb  push_back
#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++)
#define found(s,e)  ((s).find(e)!=(s).end())

ll primes[44721];// 357768 bytes
int primes_cnt;

int e_sieve(int till)
{
  vector<bool> sieve(till+1,true);
  primes_cnt = 0;

  sieve[2] = true;
  primes[primes_cnt++] = 2;

  for (int prime=3;;) {
    primes[primes_cnt++] = prime;
    for (int i=prime*3;i<=till;i+=(prime*2)) sieve[i] = false;

    int next_prime = -1;
    for (int j=prime+2; j<=till; j+=2) {
      if (sieve[j]) { next_prime = j; break; }
    }

    if (next_prime == -1) break;
    prime = next_prime;
  }

  return primes_cnt;
}

map<int,int> prime_factors(int n)
{
  map<int,int> factors;
  for (int i=0; i<primes_cnt; i++) {
    int prime = primes[i];
    while (n % prime == 0) {
      if(found(factors,prime)) factors[prime]++;
      else factors[prime]=1;
      n /= prime;
    }
    if (n==1) return factors;
  }
  factors[n] = 1; return factors;
}

vector<ll> divisors(map<int,int> pfs){
  set<ll> s;
  s.insert(1LL);
  
  tr(pfs,it){
    ll prime=(ll)it->first,mx=it->second,n=1LL;
    set<ll> t(all(s));
    rep(i,mx) {
      n *= prime;
      tr(s,st) t.insert(n*(*st));
    }
    s=t;
  }
  vector<ll> ans(all(s));
  return ans;
}

class PointsOnCircle {
 public:
  long long count(int r) {
    // 素数を準備
    e_sieve((int)sqrt(r));

    // rを素因数分解; 2000000000 => { 2 => 10, 5 => 9 } 
    map<int,int> pfs=prime_factors(r);

    // r^2を素因数分解、というかrの結果を2乗。
    // 4で割って余りが出るものだけにしたいので、
    // ここで 2^k の係数を1以下に限定する。
    // => { 2 => (20→)1, 5 => 18 } 
    tr(pfs,it){
      it->second *= 2;
      if(it->first==2) it->second=min(2,it->second);
    }
    // 素因数分解の結果から約数を求める
    vector<ll> ds = divisors(pfs);

    // 4*(d1(n)-d3(n))を求める
    ll c=0LL;
    tr(ds,it){
      int rm=(*it)%4;
      if(rm==1) c++;
      else if(rm==3) c--;
    }
    return c<<2;
  }
};

SRM366 Div1 Easy: ChangingSounds

| 05:33 | SRM366 Div1 Easy: ChangingSounds - naoya_t@topcoder を含むブックマーク はてなブックマーク - SRM366 Div1 Easy: ChangingSounds - naoya_t@topcoder SRM366 Div1 Easy: ChangingSounds - naoya_t@topcoder のブックマークコメント

231.62点。(7'55") // Passed System Test

変数名を打ち込む時間が勿体ない。使ってないマクロを消す時間が勿体ない。

class ChangingSounds {
 public:
  int maxFinal(vector<int> changeIntervals, int beginLevel, int maxLevel) {
    int n=sz(changeIntervals);
    bool lev[2][maxLevel+1];
    rep(i,maxLevel+1) lev[0][i]=lev[1][i]=false;
    lev[0][beginLevel]=true;
    rep(s,n){
      int ci=changeIntervals[s];
      rep(i,maxLevel+1) lev[(s+1)%2][i]=false;
      rep(i,maxLevel+1) {
        if(lev[s%2][i]){
          if(i+ci<=maxLevel) lev[(s+1)%2][i+ci]=true;
          if(i-ci>=0) lev[(s+1)%2][i-ci]=true;
        }
      }
    }
    for(int i=maxLevel;i>=0;i--){
      if(lev[n%2][i]) return i;
    }
    return -1;
  }
};

SRM367 Div1 Easy: ObtainingDigitK

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

速攻でsubmitできた(248.28point)、と思ったら問題読めてなかった。問題文のテストケースは通るがFailed System Test...

  • 場合分けしようかと思ったが、全桁計算した方が確実な気が
  • 二度目のsubmit(148.80point)でPassed System Test
#define rep(var,n)  for(int var=0;var<(n);var++)

class ObtainingDigitK {
  vector<int> ds;
  int l,k_;
  bool inc(){
    for(int i=l;i>=0;i--){
      if(ds[i]==9){
        ds[i]=0;
        if(k_==0) return true;
      }else{
        ds[i]++;
        return (ds[i]==k_);
      }
    }
    return false;
  }
 public:
  int minNumberToAdd(string originalNumber, int k) {
	l=originalNumber.length(); k_=k;
    ds.resize(l+1);
    ds[0]=0;
    rep(i,l) {
      ds[i+1]=originalNumber[i]-'0';
      if(ds[i+1]==k) return 0;
    }
    for(int i=1;i<=10;i++){
      //cout << "ds: " << ds << endl;
      if(inc()) return i;
    }
    return 222;
  }
};

SRM368 Div1 Easy: JumpingBoard

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

3回目のsubmitでやっとSystem Testに通った。

  • とりあえずBFSで探索
  • 既に通った場所に戻ってきたら無限ループ可能なので-1を返す。が、BFSでやるなら通過履歴はちゃんとクリアしないと駄目
  • メモ化しないとTLE
typedef vector<string> vs;
#define sz(a)  int((a).size())
#define mset(arr,val)  memset(arr,val,sizeof(arr))
#define found(s,e)  ((s).find(e)!=(s).end())

#define xy(x,y) (((x)<<6)|(y))
#define num(c) ((c)=='H')?-1:((c)-'0')

class JumpingBoard {
  vs orig;
  bool bd[50][50];
  int h,w;
  map<int,int> memo;
  
  int sub(int mv,int x,int y){
    int key=xy(x,y);
    if(found(memo,key)) return mv+memo[key];
    if(bd[x][y]) return -1;
    bd[x][y]=true;
    int a=num(orig[y][x]);
    int rmax=mv+1;
    if(x>=a && orig[y][x-a]!='H') {
      int r=sub(mv+1,x-a,y); if(r==-1) return -1;
      rmax=max(rmax,r);
    }
    if(x+a<w && orig[y][x+a]!='H') {
      int r=sub(mv+1,x+a,y); if(r==-1) return -1;
      rmax=max(rmax,r);
    }
    if(y>=a && orig[y-a][x]!='H') {
      int r=sub(mv+1,x,y-a); if(r==-1) return -1;
      rmax=max(rmax,r);
    }
    if(y+a<h && orig[y+a][x]!='H') {
      int r=sub(mv+1,x,y+a); if(r==-1) return -1;
      rmax=max(rmax,r);
    }
    bd[x][y]=false;
    memo[key]=rmax-mv;
    return rmax;
  }

 public:
  int maxJumps(vector<string> board) {
    orig=board;
    h=sz(board); w=sz(board[0]);
    mset(bd,0);
    return sub(0,0,0);
  }
};
トラックバック - https://topcoder-g-hatena-ne-jp.jag-icpc.org/n4_t/20090117