競技プログラミング日記

主に AtCoder の記事です

第七回 アルゴリズム実技検定 I問題

 

PAST007I

複素数
回転と平行移動のみなので,複素数による実装が簡単.

実装
右目と左目を区別することに注意. よって,平行移動と回転は一意に定まる.
操作後の点たちを,平行移動 -> 回転 の順で求める. 平行移動を忘れずに.

使っている記号,マクロ等 "https://ecsmtlir.hatenablog.com/entry/2022/12/23/131925"

//---------------------------------------------------------------------------------------------------

// Complex numbers
  template<typename T>
  class ComNum{
    pair<T,T> pa; // <re, im>
  public:
    ComNum<T>(){ pa.first = 0, pa.second = 0; }
    ComNum<T>(T sc){ pa.first = sc, pa.second = 0; }
    ComNum<T>(T x, T y){ pa.first=x, pa.second=y; }
    void set_re(T x){ pa.first=x; };
    void set_im(T y){ pa.second=y; };
    T re(){ return pa.first; }
    T im(){ return pa.second; }
   
    ComNum<T> inv (){ // return inverse of (*this)
      T x,y; x = (*this).re(),  y = (*this).im();

      if(x==0 && y==0) return ComNum(); // fail

      T n2 = x*x + y*y;
      return ComNum(x/n2, -y/n2);
    }
    T norm2(){
      return pa.first*pa.first + pa.second*pa.second;
    }

    T norm(){
      return sqrt(norm2());
    }
   
    ComNum<T> operator * (T sc){ return ComNum<T>*1; }
    ComNum<T> operator - (ComNum<T> b){ return (*this) + (b*(-1)); }
    ComNum<T> operator * (ComNum<T> b){
      T x,y,z,w;
      x = (*this).re(),   y = (*this).im();
      z = b.re(),     w = b.im();
      return ComNum<T>(x*z-y*w, x*w+y*z);
    }
    ComNum<T> operator / (ComNum<T> b){ return (*this)*b.inv(); }
   
  };
  template<typename T> ComNum<T> operator * (T sc, ComNum<T> b){ return b*sc; }
  template<typename T> ComNum<T> operator / (T sc, ComNum<T> b){ return b/sc; }

  template<typename T> bool operator == (ComNum<T> a, ComNum<T> b){
    return a.re() == b.re() && a.im() == b.im();
  }
  template<typename T> bool operator != (ComNum<T> a, ComNum<T> b){
    return !(a == b);
  }
 

//---------------------------------------------------------------------------------------------------
int main() {
  using C = ComNum<double>;
  ll n;
  cin >> n;

  vector<C> eye(2); // [1] : left
  rep(i,2) {
    double x,y;
    cin >> x >> y;
    eye[i] = C(x,y);
  }

  vector<C> b;
  rep(i,n){
    ll s,t; cin >> s >> t;
    b.push_back(ComNum<double>(s,t));
  }

  C ce = (eye[0] + eye[1])/2.0;
  double e = (eye[1] - ce).norm();
  C th = (eye[1] - ce) / C(e, 0.0);

  rep(i,n){
    C z = (b[i] - ce)/th;
    printf("%.10lf %.10lf\n", z.re(), z.im());
  }


  return 0;
}

*1:*this).re()*sc, (*this).im()*sc); }

    ComNum<T> operator / (T sc){ return (*this)*(1/sc); } // Remark : 1/sc if T is integer case
    ComNum<T> operator + (ComNum<T> b){ return ComNum<T>((*this).re()+b.re(), (*this).im()+b.im(