https://yukicoder.me/problems/no/895
解説
https://yukicoder.me/submissions/384932
最後の条件がなかなか見慣れないので、考えてみよう。
これは、全てのビットかかぶらず、かつ、下位a+b+cビットに全部集まっていることを示している。
なので、a+b+c個ある1をx,y,zに割り振っていく問題と捉えていこう。
2番目の条件x > y > zは、それぞれの最上位ビットだけを見れば条件を満たすかがわかる。
この最上位ビットだけを考えてやれば、他の部分は適当に分配できそう?
いや、全探索と言っても、a+b+c番目の1は、xが取る必要がある。
yの最上位ビットを全探索してやれば、良さそうか?
良さそうだな。
yの最上位ビットがyi番目のとき、
[a+b+c,yi)番目のビットはすべてxのものになる。
(yi,1]番目の1は、xyzのどれに振ってもx>y>zの条件は満たすので大丈夫。
あとは、a,b,c個になるように計算する必要がある。
すでにxは(a+b+c)-yi個とっているし、yは1個とっているのでそれは減らそう。
(yi-1)個をa個b個c個の3グループに分ける。
zの総和に関係してくるのは、(yi-1)個からc個とってくる部分。
あるビットが1になっている組み合わせは、(yi-2)!/{a!b!(c-1)!}である。
これはどのビットについても組み合わせは変わらない。
よって、(1+2+4+8+...+2yi-1)*(yi-2)!/{a!b!(c-1)!}がyi固定としたときのzの取りうる値の総和になる。
int a, b, c; Comb<mint, 301010> com; //--------------------------------------------------------------------------------------------------- void _main() { cin >> a >> b >> c; mint ans = 0; mint z_tot = 1, z_cur = 1; rep(yi, 2, a + b + c) { int aa = a - (a + b + c - yi); int bb = b - 1; int cc = c; if (0 <= aa and 0 <= bb) { ans += com.fac[yi - 2] / (com.fac[aa] * com.fac[bb] * com.fac[cc - 1]) * z_tot; } z_cur *= 2; z_tot += z_cur; } cout << ans << endl; }