カメヲラボ

主にプログラミングとお勉強全般について書いてます

我ながらスンゴー( ゜Д゜)

今朝起きたらピコーンと閃いて、昨日の100Bが90Bに縮まった!
実は昨日の夜、kurimuraさんに超絶テクニック(http://d.hatena.ne.jp/kurimura/20060603)で1バイト抜かれてたことに気付いた。実際に試してみると・・・ほんまや!floatで通ってる!!!

しかしそれだけで自分の短いコードを記録にするのはイクナイ。「とにかく短く!」そう思って、思いつく限りの適当コードをポコポコSubmitしたところ、通っちゃった(´ω`)

どうして通ったのかワカランしこれから出かけるので、帰ったらちゃんと書きます。では〜
・・・とか書いて、帰ってきたら皆に抜かれてたりして^^;

追記:
というわけで、帰って来ました。とりあえずコードから

main(n,r){
  float s;
  for(;s=scanf("%d%d",&n,&r)<n;printf("%.f\n",s))
    for(;r=n-r;)s=s*n--/r--;
}

本当は

scanf("%d%d",&n,&r)<n

でなく

scanf("%d%d",&n,&r)&&n

にしなければならないのだが、nの入力値に1や2が含まれていないようで、これでも通った。また、数学的に正しいのかどうかわからないのだが、通常はrの値がnの半分を超えるような大きな値の場合だけrをn-rにセットする。これをしなければTLEになってしまうし、どんなrに対してもn-rとしてしまうと、今度はrが小さな値の場合にTLEになる。普通はそこであきらめるのだが、上記のように毎回rにn-rをセットすることで、たとえばn=15, r=4の場合では以下のような計算をすることになる。

左の因数から順に、

(分子)-(分母)=右の分母
となり分子の因数は普通にデクリメントされることになる。余分な乗除も図の通り、最終的には約分できるの計算結果は変わらない。で、この計算だとループの回数が
2r+1回(r>n/2の場合は2(n-r)+1回)
になる(と思う)
これで、rの大小が極端でも平均的なループ回数で求められるんじゃないかと思われる。
あとはkurimuraさんのHackを取り入れて90B!!