土下座しながら探索中

主に競技プログラミング

SRM 500 Div2 Hard : GeometricProgressions

問題概要 :
短いし分かりやすいので略

解法 :
素因数分解 + ローリングハッシュで通せたが怪しい気がしなくもない
愚直に値を計算すると当然オーバーフローするので、素因数分解してからq1,q2の各素因数の数だけを増やしていく感じにした
setにmapを詰めたところバッドアロックだったので、
mapの値をローリングハッシュで unsigned long long の値に変換してsetにつめたら通った

大きな値がでたら素因数分解 ( 師範代より )

コード :

typedef long long ll;
typedef unsigned long long ull;

const ull base = 1000000007ULL;

class GeometricProgressions {
public:

  map<ll,ll> prime_factor(ll n){
    map<ll,ll> ret;
    ret[1] = 1;
    for(ll i=2;i*i<=n;i++){
      while( n % i == 0LL ){
	++ret[i];
	n /= i;
      }
    }
    if( n != 1LL ) ret[n] = 1;
    return ret;
  }

  ull toHash(map<ll,ll> buf){
    ull tmp = 0;
    for(map<ll,ll>::iterator it = buf.begin(); it != buf.end(); it++ ){
      tmp *= base;
      tmp *= base;
      tmp += it->first;
      tmp *= base;
      tmp += it->second;
    }    
    return tmp;
  }

  int count(int b1, int q1, int n1, int b2, int q2, int n2) {
    map<ll,ll> pf,coef,buf;
    set<ull> S;
    pf   = prime_factor(b1);
    coef = prime_factor(q1);
    buf = pf;

    if( b1 == 0 ) {
      S.insert(0);
    } else if( q1 == 0 ){ 
      buf[1] = 1LL;
      buf[0] = 0LL;
      S.insert(toHash(buf));
      if( n1 > 1 ) S.insert(0);
    } else {
      rep(_,n1){
	buf[1] = 1LL;
	buf[0] = 0LL;
	S.insert(toHash(buf));
	for(map<ll,ll>::iterator it = coef.begin(); it != coef.end(); it++ ) {
	  buf[it->first] += it->second;
	  assert( buf[it->first] > 0 );
	}
      }
    }

    pf   = prime_factor(b2);
    coef = prime_factor(q2);
    buf = pf;
    if( b2 == 0 ) {
      S.insert(0);
    } else if( q2 == 0 ){ 
      if( n2 > 1 ) S.insert(0);
      buf[1] = 1LL;
      buf[0] = 0LL;
      S.insert(toHash(buf));

    } else {
      rep(_,n2){
	buf[1] = 1LL;
	buf[0] = 0LL;
	S.insert(toHash(buf));
	for(map<ll,ll>::iterator it = coef.begin(); it != coef.end(); it++ ) {
	  buf[it->first] += it->second;
	  assert( buf[it->first] > 0 );
	}
      }
    }
    return S.size();
  }
};