読者です 読者をやめる 読者になる 読者になる

メモ

yukicoderで遊んでいる競プロゆるふわ勢

yukicoder No.221 犯罪都市

問題はこちら
No.221 犯罪都市 - yukicoder

条件付き確率の問題
1万人あたりN人がマフィアなので、「構成員」と判定される人数は1万人あたり
(10000-N)*0.01+N*0.99 人となる
実際には構成員でない人は(10000-N)*0.01 人なので、誤認逮捕率は
((10000-N)*0.01)/((10000-N)*0.01+N*0.99) となる。答えは百分率で求めるので100倍して分母を整理すれば
(10000-N)/(10000+98N) を得る。

int main(){
	int n;
	scanf("%d",&n);
	printf("%f",(10000.0-n)/(10000+98*n));
	return 0;
}

式を変形してnを1箇所にまとめればscanfを使わなくてもgets+atoiで短縮できそう。
N≠10000なら\frac{10000+98N}{10000-N}=\frac{990000}{10000-N}-98なのでこれより求めるべき答えは
100/(99e4/(1e4-n)-98)=1/(9900/(1e4-n)-0.98) となる
ところでN=10000のときも 1e4-nは0 → 9900/(1e4-n)-0.98はInf → 1/(9900/(1e4-n)-0.98)は0 となり期待通りの答えを得られる

n;main(){n=!printf("%f",1/(9900/(1e4-atoi(gets(&n)))-.98));}

60B

ふと上位に目をやると最短がperl 30B
……「print 1/(9900/(1e4-<>)-.98)」で27Bじゃね?
と思ったのだけど、perlは0除算をするとREになるようだ。ぐぬぬ
仕方ないので逆数を使わずに攻める
\frac{1000000-100N}{10000+98N}=\frac{1}{98}(\frac{99000000}{10000+98N}-100)を使って

print+(99e6/(1e4+98*<>)-100)/98
print+(99e4/(1e4+98*<>)-1)/.98
print+(99/(1+.0098*<>)-1)/.98

ということで29Bが作れた


5/19 追記
カッコ外してみたい…外してみたくない?

print+(99/(1+.0098*<>)-1)/.98
print+9900/(98+.9604*<>)-1/.98
#そういえばこれって制約ゆるいし、多少ごまかしてもいけるんじゃね?
print+9900/(98+.96*<>)-1.02

というかどうせ近似式作るならガチでやろう
求める答えは1次式÷1次式の分数関数だったんだから\frac{p}{N+q}+rの形で書ける
式変形をすると厳密解は
p=99000000/9604=10308.2…,
q=10000/98=102.04…,
r=100/98=1.02…
となるのでとりあえず適当なところで打ち切って

print+10308/(102+<>)-1.02

1.02っていうの1にできないかな?
第1項も適当に小さくすればいいから p/(102+N)-1 の形で条件にあうpを探す
10201≦p≦10203 が得られるので

print+10201/(102+<>)-1

で22B。計算で求めるなら恐らくこれが限界

ということでこれにともなってCも書き換え

n;main(){n=!printf("%f",10201./(102+atoi(gets(&n)))-1);}

56B