問題はこちら
No.24 数当てゲーム - yukicoder
答えの可能性が残っているかどうかをbitで保存しておく
質問した4数もbitで保存して、YESならbitand、NOならbitnotしてからbitand
最終的にはbitが残っているのは1箇所だけになるのでそこを出力
int main(){ int n=1023,t,i,x,y; //nに情報を保存。初期値として0~9までbitを立てておく char s[4]; scanf("%d",&t); while(t--){ x=0;i=4; while(i--){ scanf("%d",&y); x|=1<<y; //読み込んだ数をbitで保存 } scanf("%s",s); n&=*s=='N'?~x:x; //読み込んだ文字列はstrcmpしなくても1文字目だけ見れば判別可能 } i=0; while(n/=2)i++; printf("%d\n",i); return 0; }
nの初期化がいやだからbitの保存を逆にする。つまり、答えではないことが確定したところにbitがたつ
あとは1つ目の数を読み飛ばしたりいつもどおり短縮
char s[4]; n,x; main(y){ for(;gets(s);)for(n|=*s>78?~x:x,x=0;scanf("%d",&y)>0;x|=1<<y); //文字列がきたせいでscanfできなくなった時は-1ではなく0が返ってくる //ループを抜けたときxは0 for(;n&1<<x;x++); x=!printf("%d",x); }
scanfの読み込み失敗によってYES,NOの前の空白が読み飛ばされるのでgetsで読めるようになっている
charと書くのはまどろっこしい
ところでCではリトルエンディアンで値が保存されているので
int s;
gets(&s);
を実行すると、NOだった時には'N'+('O'<<8)=20302が、YESだと5457241が返ってくる。
(実際には後ろの方に前のデータが残ることがあることに注意)
これを利用して次のように短縮できる
s,n,x; main(y){ for(;gets(&s);)for(n|=s>3e4?~x:x,x=0;scanf("%d",&y)>0;x|=1<<y); for(;n&1<<x;x++); x=!printf("%d",x); }
114B
2017/07/30追記
Aの最下位bitはA&-Aで得られたので、次のように短縮できる
s,n,x; main(y){ for(;gets(&s);)for(n|=s>3e4?~x:x,x=0;scanf("%d",&y)>0;x|=1<<y); printf("%.f",log2(~n&-~n)); }
入力に1つでもYESがあれば~nは1<< ansに一致するが、すべてNOだったときはその-1倍になるので、&以下が必要
この手間を嫌ってnに保存するbitを反転させても同じ長さになった
s,n,x;main(y){for(;gets(&s);)for(n|=s>3e4?~x:x,x=0;scanf("%d",&y)>0;x|=1<<y);printf("%d",log2(~n&-~n));} s,n=1023,x;main(y){for(;gets(&s);)for(n&=s>3e4?x:~x,x=0;scanf("%d",&y)>0;x|=1<<y);printf("%d",log2(n));}
105B