yukicoder No.67 - よくある棒を切る問題 (1)(writer担当)

Source

ニコニコミュニティ
問題文

問題概要

$N$ 個の棒があり,棒 $i$ の長さは $L_i$ である.
棒を自由に切れるとして,同じ長さの方を $K$ 本作りたい.
その棒の長さの最大値を求める問題.

解法

答えに対する二分探索する.
答えを決めつければ,各棒から何本取れるかは割り算で決まる.
棒の数は $32$ ビット整数型に収まらないことに注意.
また,二分探索の終了条件を絶対誤差が $10^{-9}$ 以下などとすると,答えが大きい時に無限ループに陥るので注意.
時間計算量は,許容誤差を $\varepsilon$ として $O(N \log (1/\varepsilon))$ 程度.

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)

#define ll long long
#define EPS 1e-9

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 reader(ll *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);}

int N;
int A[200000];
ll K;

int main(){
  int i, j, loop;
  double a, b, c, d;
  ll val;

  reader(&N);
  rep(i,N) reader(A+i);
  reader(&K);

  assert(1 <= N && N <= 200000);
  rep(i,N) assert(1 <= A[i] && A[i] <= 1000000000);
  assert(1LL <= K && K <= 10000000000LL);

  a = 0; b = 1e10;
  while(b > a+EPS && b > a*(1+EPS)){
    c = (a+b)/2;
    d = 1.0 / c;
    val = 0;
    rep(i,N) val += (ll)(A[i]*d);
    if(val >= K) a = c; else b = c;
  }

  printf("%.10f\n",(a+b)/2);

  return 0;
}

Current time: 2017年11月21日04時14分45秒
Last modified: 2014年11月17日00時11分07秒 (by laycrs)
Tags: Competitive_Programming yukicoder
トップページに戻る

Logged in as: unknown user (not login)

ログイン: