問題はこちら
No.197 手品 - yukicoder
場合分け
・コインの数が変わっていたら成功
・そうでないとき
N≧2なら任意の状態にできることが確かめられるので失敗(ooo,oox,oxo,xooを調べれば十分)
N=1ならシミュレーションで確かめる
N=0なら前後で変化していれば成功
・さもなくば失敗
int main(){ char b[4],a[4]; int bo,ao,n,i; gets(&b); for(i=0;i<3;i++)b[i]=='o'?bo++:0; //操作前のoの個数 scanf("%d\n",&n); gets(&a); for(i=0;i<3;i++)a[i]=='o'?ao++:0; //操作後のoの個数 if(ao!=bo){puts("SUCCESS");return 0;} //oの数が変わっていたら成功 if(n>=2){puts("FAILURE");return 0;} //n>=2なら失敗 if(n==0){puts(strcmp(a,b)?"SUCCESS":"FAILURE");return 0;} //n==0なら前後で変化していれば成功 if(strcmp(b,"oxo")==0&&strcmp(a,"oxo")==0 ||strcmp(b,"xox")==0&&strcmp(a,"xox")==0 ||strcmp(b,"xoo")==0&&strcmp(a,"oox")==0 ||strcmp(b,"oox")==0&&strcmp(a,"xoo")==0 ||strcmp(b,"oxx")==0&&strcmp(a,"xxo")==0 ||strcmp(b,"xxo")==0&&strcmp(a,"oxx")==0)puts("SUCCESS"); //n==1なら上の6通りのいずれかなら成功 puts("FAILURE"); //さもなくば失敗 return 0; }
'o'は111で'x'は120なので最下位bitを見れば判断できる
ということはint a;gets(&a);a&=0x10101;で必要な情報は得られる
さらにこのaに対し、a%255でxの数が、a%254で「oを0、xを1として3文字を2進数とみなしたもの」が得られる(少し考えれば明らか)
またnの値も「0,1,それ以外」を判断できれば良いのでgetsでまとめてしまって良い
a,b; main(s){ gets(&a);gets(&s);gets(&b); a&=65793;b&=65793; a=!puts((a-b)%255|(s-48?s-49?0:(a=a%254*b%254)==4|a==18|a==25:a-b)?"SUCCESS":"FAILURE"); //Nが1のときの場合分けは、積でうまく計算できることが確かめられる }
a&=0x10101ってまだるっこしくない?
ということで、これをしなくてもうまくいくものを探すと
a,b; main(s){ gets(&a);gets(&s);gets(&b); a=!puts((a-b)%5|(s-48?s-49?0:a%7*b%7==1:a-b)?"SUCCESS":"FAILURE"); }
とすっきり書ける
106B
一応確認すると、
文字列 | aの値 | a%5 | a%7 |
---|---|---|---|
ooo | 7303023 | 3 | 0 |
xoo | 7303032 | 2 | 2 |
oxo | 7305327 | 2 | 1 |
oox | 7892847 | 2 | 4 |
xxo | 7305336 | 1 | 3 |
xox | 7892856 | 1 | 6 |
oxx | 7895151 | 1 | 5 |
xxx | 7895160 | 0 | 0 |
となっており、a%5==b%5(即ちoの数が一致)かつs==1の時も
before | after | a%7 | b%7 | a%7*b%7 |
---|---|---|---|---|
xoo | oxo | 2 | 1 | 2 |
oxo | oox | 1 | 4 | 4 |
oox | xoo | 4 | 2 | 1 |
xoo | xoo | 2 | 2 | 4 |
oxo | oxo | 1 | 1 | 1 |
oox | oox | 4 | 4 | 2 |
xxo | xox | 3 | 6 | 4 |
xox | oxx | 6 | 5 | 2 |
oxx | xxo | 5 | 3 | 1 |
xxo | xxo | 3 | 3 | 2 |
xox | xox | 6 | 6 | 1 |
oxx | oxx | 5 | 5 | 4 |
と、見事にうまく言っていることが確認できる
2016/05/19追記
puts((a-b)%5|(s-48?s-49?0:a%7*b%7==1:a-b)?"SUCCESS":"FAILURE"); puts((a-b)%5|(s-48?s==49&a%7*b%7==1:a-b)?"SUCCESS":"FAILURE");
として1B短縮で105B
こういう自明なのを見落としているうちはまだまだ初心者である
2016/06/23追記
a,b;main(s){gets(&a);gets(&s);gets(&b);a=!puts((s-48?(a-b)%5|s==49&a%7*b%7==1:a-b)?"SUCCESS":"FAILURE");} a,b;main(s){gets(&a);gets(&s);a=gets(&b)<puts((s-48?(a-b)%5|s==49&a%7*b%7==1:a-b)?"SUCCESS":"FAILURE");}
1B短縮で104B。またも自明な見落とし
2016/10/17追記
a,b;main(s){gets(&a);gets(&s);a=gets(&b)<puts((s-48?(a-b)%5|s==49&a%7*b%7==1:a-b)?"SUCCESS":"FAILURE");} a,b;main(s){gets(&a);gets(&s);a=gets(&b)<puts((s-48?(a-b)%5|s<50&a%7*b%7==1:a-b)?"SUCCESS":"FAILURE");}
自明な1B短縮で103B