問題はこちら
No.441 和か積 - yukicoder
場合分けをすれば簡単に分かる。
必要ならAとBを入れ替えることでA≦Bと仮定して良い
・Aが0のとき
Bも0なら'E'、さもなくば'S'
・Aが1のとき
必ず'S'
・Aが2のとき
Bも2なら'E'、さもなくば'P'
・Aが3以上のとき
必ず'P'
Cでは200桁の整数を受け取るのは難しい。
上の場合分けを見ると、AもBも「3以上」はまとめて扱って良いことに気づく。
つまり、値が3以上ならそれを3に置き換えても結果に影響しない。
(上のように厳密に場合分けしなくても、例えば「値が10000以上なら10000に置き換えても和と積の大小関係は変わらなくない?」というのはイメージできると思う)
ということで、次のようにできる
int main(){ char s[300]; int a,b; scanf("%s",s); a=strlen(s)>1?9:atoi(s);//2桁なら9にしてしまう scanf("%s",s); b=strlen(s)>1?9:atoi(s);//同上 if(a*b==a+b)putchar('E'); else if(a*b>a+b)putchar('P'); else putchar('S'); return 0; }
この方針のまま縮めるとこう
char s[999]; a; main(b){ scanf("%s ",s); a=strlen(s)>1?9:*s-48; b=strlen(gets(s))>1?9:*s-48; a=!putchar(a*b-a-b?a*b<a+b?83:80:69); }
でもstrlenは長いし、getcharかreadでいい感じにやりたい
とりあえずぱっと思いつく簡単なやつ
#define f(x)for(;(t=getchar())>32;x=x?9:t-48); //a,bは最初は0。先頭の桁を保存した後、もし2桁目以降があれば9に書き換える a,b; main(t){ f(a); f(b); a=!putchar(a*b-a-b?a*b<a+b?83:80:69); }
これをぐっと睨んでdefineをどうにかすると
t,a,b; main(i){ for(;read(0,&t,1);t>32?b=b?9:t-48:i--?a=b,b=0:0); a=!putchar(a*b-a-b?a*b<a+b?83:80:69); }
このようになる。
ところで最後の条件式はa*b-a-b=(a-1)*(b-1)-1であることから、a,bに実際の数より1小さな値が入るように予め調整しておけば次のように短くできる
putchar(a*b-a-b?a*b<a+b?83:80:69); putchar(a*b-1?a*b<1?83:80:69);
さらに、readをfor文の終了条件にしていると、returnがいい感じになるような気がしたので、最後の代入も省略して
t,a,b;main(i){for(;read(0,&t,1);t>32?b=b?9:t-49:i--?a=b,b=0:putchar(a*b-1?a*b<1?83:80:69));}
92B
2018/01/24追記
よくみるとこれは嘘解法。
例えば「12 2」などで落ちる。
修正してもよいが、じつは愚直解のほうがよほど短くなる。
double a,b; main(){ scanf("%lf%lf",&a,&b); putchar(a-b||(a&&a-2)?a*b>a+b?80:83:69); }
81B
これが上手く動作することの証明には、丸め誤差の取扱などに熟知している必要がある。面倒くさいのでここでは省略するが、このプログラムは常に正しい値を返す。
しかし、一見同じ動作をするようにみえる次のコードはそうではない。
double a,b; main(){ scanf("%lf%lf",&a,&b); putchar(a-b||(a&&a-2)?a*b<a+b?83:80:69); }
aが十分大きな値であり、b=1のとき、a+bは情報落ちによりaとなってしまう。