あああああ

オタク & 競プロ

AGC035-F Two Histograms 別解

 

問題

atcoder.jp

 

解法

 

上の行から決めていきます。

i 行目のマスを全て決めた時、l_j >= i となる j がなるべく多くなるように k, l を決めておいて損しません。

 

いま、i - 1 行目までのマスを決めたときの l_j >= i - 1 とできる j の集合が S であるとします。

l_j >= i とできる j の集合が T となるような i 行目のマスの決め方が何通りあるかを考えます。

 

これは簡単な式になって、

T が S の部分集合でない時は 0 通りで、

部分集合の時は、W + 1 - (|S| - |T|) となります。

 

k_i は基本的には 0 以上 W 以下の全ての値を取れますが、k_i = x かつ x は S に含まれるかつ x は T に含まれない、とすることは不可能(その場合は k_i = x - 1 として x を T に含めていいため)であることからこの式が出てきます。

 

dpしたくなって、適当な係数をかければ集合のサイズでまとめて良いことから、l_j < i となった要素の個数に注目して書くと、

 

mint ans=0;

    

    vector<mint> pa(W+1);pa[0]=1;

    

    for(int t=1;t<=H;t++){

        vector<mint> ne(W+1);

        for(int j=0;j<=W;j++){

            for(int a=0;a+j<=W;a++){

                ne[a+j]+=pa[j]*comb(a+j,a)*(W+1-a);

            }

        }

        pa=ne;

    }

    

    for(int j=0;j<=W;j++){

        ans+=pa[j]*comb(W,j);

    }

    

    cout<<ans.val()<<endl;

 

このような3乗解にできます。

 

グッと睨むと結局多項係数になってるじゃん、ということでその部分をバラすと、

 

{ (W+1-i) / i! * x^i } ^ H * (1 / i! * x^i) の x^W の係数 * W! が答えになります。

 

これは結局 (W+1-x)^H * exp((H+1)*x) になるので、

(W+1-x)^H = comb(H,j) * (W+1)^j * (-x)^(H-j) の 0<=j<=H についてのsum

を利用することでO(H+W)で解くことができました。

 

提出

https://atcoder.jp/contests/agc035/submissions/39384404

 

感想

まさか自分が詰めをFPSでできるなんて!?と感動していたりする

最初は式変形が下手くそすぎてpowにしかならずに窃盗して通して、そのあともう一度考え直した、使いこなすのはまだ遠い