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

メモ

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

yukicoder No.197 手品

問題はこちら
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