Yandex.Algorithm 2015 Round 2.2 D問題 - Sequence of Triangles

Source

Yandex.Algorithm 2015
Yandex.Algorithm 2015 Round 2.2
問題文

問題概要

整数の長さ $m$ の線分があるとき,それを斜辺とする全ての辺の長さが整数の直角三角形を作り,斜辺でないどちらかの辺のみを残し,残りの $2$ 辺を消すという操作を考える.
正整数 $L$ が与えられるので,最初長さ $L$ の線分があるとき,上の操作は最大で何回繰り返すことができるかを求める問題.

解法

$a^2+b^2=c^2$ を満たす正整数の組(ピタゴラス数) $(a,b,c)$ を列挙した後,操作によってどの長さからどの長さにできるかという関係を用いてDPすれば良い.
列挙には,$(a,b,c)$ が互いに素なものは,$(m^2-n^2, 2mn, m^2+n^2)$ と表されることを利用すると十分時間内に列挙できる.
ただし,$m-n$ は正の奇数で,$m,n$ は互いに素.

C++によるスパゲッティなソースコード

#include<bits/stdc++.h>
using namespace std;

#define REP(i,a,b) for(i=a;i<b;i++)
#define rep(i,n) REP(i,0,n)

#define mygc(c) (c)=getchar_unlocked()
#define mypc(c) putchar_unlocked(c)

void reader(int *x){int k,m=0;*x=0;for(;;){mygc(k);if(k=='-'){m=1;break;}if('0'<=k&&k<='9'){*x=k-'0';break;}}for(;;){mygc(k);if(k<'0'||k>'9')break;*x=(*x)*10+k-'0';}if(m)(*x)=-(*x);}
void writer(int x, char c){int s=0,m=0;char f[10];if(x<0)m=1,x=-x;while(x)f[s++]=x%10,x/=10;if(!s)f[s++]=0;if(m)mypc('-');while(s--)mypc(f[s]+'0');mypc(c);}
template<class T> void writerLn(T x){writer(x,'\n');}

template<class T> T GCD(T a,T b){T r; while(a){r=b; b=a; a=r%a;} return b;}

vector<int> edge[1000001];
int dp[1000001];

int main(){
  int i, j, k, L;
  int a, b, c;

  for(i=1;;i++){
    if(i*i > 1000000) break;
    for(j=1;j<i;j++){
      a = i*i - j*j;
      b = 2*i*j;
      c = i*i + j*j;
      if(c > 1000000) break;
      if(GCD(a,b)>1) continue;

      for(k=1;k*c<=1000000;k++){
        edge[k*c].push_back(k*a);
        edge[k*c].push_back(k*b);
      }
    }
  }

  rep(i,1000001){
    rep(j,edge[i].size()){
      k = edge[i][j];
      dp[i] = max(dp[i], dp[k]+1);
    }
  }

  reader(&L);
  writerLn(dp[L]);

  return 0;
}

Current time: 2017年07月23日15時37分13秒
Last modified: 2015年09月09日05時42分44秒 (by laycrs)
Tags: Competitive_Programming Yandex_Algorithm Yandex_Algorithm_2015 Yandex_Algorithm_2015_Round22
トップページに戻る

Logged in as: unknown user (not login)

ログイン: