[Tyvj 2869] 혈연관계

혈연관계
시간 제한: 1 Sec 메모리 제한: 128 MB
제목 설명
우 리 는 요괴 가문 의 혈연 관 계 를 연구 하고 있다.모든 요 괴 는 같은 수량의 유전 자 를 가지 고 있 지만, 서로 다른 요괴 의 유전 자 는 다 를 수 있다.우 리 는 임의로 주어진 두 요괴 사이 에 도대체 얼마나 같은 유전자 가 있 는 지 알 고 싶다.유전자 수가 상당히 많 기 때문에 직접 검 사 는 통 하지 않 는 다.그러나 우 리 는 요괴 가족의 가 보 를 알 고 있 기 때문에 우 리 는 가보 에 따라 두 요괴 사이 의 같은 유전자 의 수량 을 추산 할 수 있다.요괴 간 의 유전자 상속 관 계 는 상당히 간단 하 다. 만약 에 요괴 C 가 요괴 A 와 B 의 아이 라면 C 의 임의의 유전 자 는 A 나 B 의 유전 자 를 계승 할 수 있 고 A 나 B 를 계승 할 확률 은 각각 50% 를 차지한다.모든 유전 자 는 서로 독립 된 것 으로 볼 수 있 으 며, 모든 유전자 의 계승 관 계 는 다른 유전자 의 영향 을 받 지 않 는 다.이제 두 요괴 X 와 Y 의 유전자 유사 도 를 정의 합 니 다.예 를 들 어 한 가족 이 있 는데 이 가족 중 에 아무런 관계 가 없 는 요괴 A 와 B, 그리고 그들의 아이 C 와 D 가 있다.그러면 C 와 D 의 비슷 한 정 도 는 얼마 일 까요?C 와 D 의 유전 자 는 모두 A 와 B 에서 나 왔 기 때문에 확률 적 으로 각각 50% 를 차지한다.따라서 C 와 D 는 확률 에 따라 평균 50% 의 동일 유전자 가 있 고 C 와 D 의 유전자 유사 도 는 50% 이다.주의해 야 할 것 은 A 와 B 사이 에 같은 유전자 가 존재 한다 면 C 와 D 의 유전자 유사 도 는 더 이상 50% 가 아니다.당신 의 임 무 는 주어진 가보 와 쌍 을 이 루 는 요괴 에 대해 유전자 의 유사 도 를 계산 하 는 프로그램 을 쓰 는 것 입 니 다.
입력
첫 줄 의 두 정수 n 과 k.n (2 ≤ n ≤ 300) 은 가족 중의 구성원 수 를 나타 내 는데 각각 1, 2,..., n 으로 표시 한다.k (0 ≤ k ≤ n - 2) 는 이 가족 중 부모 의 요괴 수량 (기타 요 괴 는 부모 가 없 으 며, 그들 사이 에는 아무런 관계 가 없다 고 생각 할 수 있 으 며, 즉 어떠한 동일 한 유전자 도 없다) 을 나타 낸다.다음 k 줄 은 줄 마다 세 개의 정수 a, b, c 로 요괴 a 는 요괴 b 와 c 의 아이 임 을 나타 낸다.그 다음 에 한 줄 의 정수 m (1 ≤ m ≤ n2) 로 유전자 유사 도 를 계산 해 야 하 는 요괴 대 수 를 나타 낸다.다음 m 행 은 줄 마다 두 개의 정수 로 유전자 의 유사 도 를 계산 해 야 한 다 는 두 개의 요 괴 를 나타 낸다.너 는 이곳 에서 제시 한 가 보 는 항상 합 법 적 이 라 고 생각 할 수 있다.구체 적 으로 말 하면 어떤 요괴 도 자신의 조상 이 되 지 않 을 뿐만 아니 라, 성별 착란 문제 도 걱정 할 필요 가 없다.
출력
총 m 행.k 행 은 k 가 요괴 간 의 유전자 유사 도 를 나타 낸다.백분율 로 출력 해 야 합 니 다. 정밀도 가 있 는 만큼 출력 해 야 합 니 다. 그러나 0 이 남아 있 는 것 은 허용 되 지 않 습 니 다. (주의, 0.001 의 경우 0.1% 가 아니 라 0.1% 를 출력 해 야 합 니 다.)구체 적 인 격식 은 견본 을 참조한다.
샘플 입력
7 4 4 1 2 5 2 3 6 4 5 7 5 6 4 1 2 2 6 7 5 3 3
샘플 출력
0% 50% 81.25% 100%
해제
  • 핵심: dp [a, b]: = (f (x [a, 1], b) + f (x [a, 2], b) / 2
  • 고정 소수
    var
     dp:array[0..300,0..300]of longint;
     p:array[0..300,0..300]of longint;  //p[i,j]: i    p[i,j] p[i,0]: i p[i,0]   
     w,x:array[0..300,1..2]of longint;  //x[i,1/2]: i    w[i,1]:   i      w[i,1] w[i,2]:  i     w[i,2]
     rudu:array[0..300]of longint;   // i   
     tt:array[0..90000,-1..300]of integer;
     z:array[0..300]of longint;
     t:ansistring;
     i,j,k,l,o:longint;
     n,m,ans:longint;
     a,b,c,v:longint;
    
    procedure did(kk,a,b:longint);
    var i,j,max,yu,ax,m,n,v:longint;
    begin
     if tt[a,-1]>tt[b,-1]
     then max:=tt[a,-1]
     else max:=tt[b,-1];
     yu:=0;
     for i:=max downto 0 do
      begin
       tt[kk,i]:=(tt[a,i]+tt[b,i]+yu) mod 10;
       yu:=(tt[a,i]+tt[b,i]+yu) div 10;
      end;
     if (tt[kk,max]=0)and(max>=1)
     then dec(max);
     tt[kk,-1]:=max;
     yu:=0;
     for i:=0 to max do
      begin
       v:=tt[kk,i]+yu*10;
       tt[kk,i]:=v div 2;
       yu:=v mod 2;
      end;
     if yu<>0
     then begin tt[kk,-1]:=max+1; tt[kk,max+1]:=5; end;
    end;
    
    function f(a,b:longint):longint;
    var c:longint;
    begin
      if (w[a,2]<w[b,2])
      then begin c:=a; a:=b; b:=c; end;
    
      if tt[dp[a,b],0]<>-1
      then exit(dp[a,b])
      else
       begin
        did(dp[a,b],f(x[a,1],b),f(x[a,2],b));//dp[a,b]:=(f(x[a,1],b)+f(x[a,2],b))/2;
        exit(dp[a,b]);
       end;
    end;
    
    begin
     readln(n,m);
     for i:=1 to m do
      begin
       readln(a,b,c);
       x[a,1]:=b; x[a,2]:=c;
       inc(rudu[a],2);
       inc(p[b,0]); inc(p[c,0]);
       p[b,p[b,0]]:=a; p[c,p[c,0]]:=a;
      end;
    
     while w[0,1]<>n do
      begin
      z[0]:=0;
      for i:=1 to n do
       if rudu[i]=0
       then
        begin
         inc(w[0,1]); w[i,2]:=w[0,1]; w[w[0,1],1]:=i;
         for j:=1 to p[i,0] do
          begin
           inc(z[0]);
           z[z[0]]:=p[i,j];
          end;
         rudu[i]:=-1;
        end;
      for i:=1 to z[0] do
       dec(rudu[z[i]]);
      end;
    
     o:=0;
     for i:=1 to n do
      for j:=1 to n do
       if i=j
       then begin inc(o); dp[i,j]:=o; tt[o,0]:=1; end
       else
        if (x[i,1]=0)and(x[j,1]=0)
        then begin  inc(o); dp[i,j]:=o; tt[o,0]:=0; end
        else begin  inc(o); dp[i,j]:=o; tt[o,0]:=-1; end;
    
     readln(m);
     for i:=1 to m do
      begin
       readln(a,b);
       ans:=f(a,b);
       for j:=tt[ans,-1] downto 1 do
        if tt[ans,j]=0
        then dec(tt[ans,j])
        else break;
       if tt[ans,0]=1
       then writeln('100%')
       else
        if (tt[ans,0]=0)and(tt[ans,-1]=0)
        then writeln('0%')
        else
         begin
          for j:=1 to 2 do
           if tt[ans,j]<>0
           then begin v:=j; break; end;
          if v=0
          then write('0')
          else
           for j:=v to 2 do
            write(tt[ans,j]);
          if tt[ans,-1]>2
          then write('.');
          for j:=3 to tt[ans,-1] do
           write(tt[ans,j]);
          writeln('%');
         end;
      end;
    end.
  • 좋은 웹페이지 즐겨찾기