HNOI2011キヤノン(組合せ論)(DP)(および除外)

ポータル

私たちは再編成、最後が、1つを考えないようにしましょう メートル メートル! その上

質問の意味:範囲内で [ 1 n個 ] [1、N] ルームを選択します メートル メートル の各要素の出現数が偶数であるような異なるセット
n個 メートル 1 E 6 N、M \ 1E6

あなたが選択したいとし K K セット、私たちが落ち着く場合 K - 1 K-1 Geは、各要素を満たすために制限の偶数であり、最後のセットが決定される
活発に D P DP ので、 F i f_i 選択を示します i 設定して法的プログラム、および除外転送の数が
減算前 k 1 K-1 セットは、最後にブランクが満たされており、プログラムの同じ番号の前にインペリアルセットと最後のものは
最初に f i 1 F_ {I-1} 二列挙重複位置
のコレクションの中で注意を命じています

f i = A 2 n 1 i 1 f i 1 f i 2 ( 2 n 1 ( i 2 ) ) ( i 1 ) f_i = A_ {2 ^ N-1} ^ {I-1} -f_ {I-1} -f_ {I-2} *(2 ^ N-1-(I-2))*(I-1)

#include<bits/stdc++.h>
#define cs const
using namespace std;
cs int Mod = 100000007;
cs int N = 1e6 + 5;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
int ksm(int a, int b){ int ans = 1; for(;b;b>>=1,a=mul(a,a)) if(b&1) ans = mul(ans, a); return ans; }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
int n, m, fac[N], f[N];
int main(){
	scanf("%d%d", &n, &m);
	int up = dec(ksm(2, n),1); fac[0] = 1; int inv = 1;
	for(int i = 1; i <= m; i++) inv = mul(inv, i); inv = ksm(inv, Mod-2);
	for(int i = 1; i <= m; i++) fac[i] = mul(fac[i - 1], (up - i + 1));
	f[0] = 1;
	for(int i = 2; i <= m; i++){
		f[i] = dec(fac[i - 1], add(f[i - 1], mul(mul(i-1, dec(up,i-2)), f[i-2])));
	} cout << mul(f[m], inv); return 0;
}
公開された610元の記事 ウォン称賛94 ビュー50000 +

おすすめ

転載: blog.csdn.net/sslz_fsy/article/details/103601764