문제에 솔루션 | 조합의 포함과 배제를 계산 bzoj2839 모음 수

백작의 컬렉션

제목 설명

N 엘리먼트의 집합은, 2 ^ N 개의 상이한 서브 세트가 (공집합 함유), 이제 그 교차점 요소 K 수 있음 2 ^ N (적어도 하나), 이러한 세트의 개수에 인출되도록 설정되어있다 프로그램의 수, 응답 모드 1000000007 획득. (아 ~는 소수이다)

입력 형식

선 두 개의 정수 N, K

출력 형식

행동 적 대답.

견본

샘플 입력

3 2

샘플 출력

6

데이터 범위 및 팁

샘플 설명

가정 원래 세트는 {A, B, C}

조건에 대한 솔루션 만족 : {AB, ABC}, {AC, ABC}, {BC, ABC}, {AB}, {AC}, {BC}

데이터 설명

데이터, 1≤N≤1000000의 100 %; 0≤K≤N;

 

 

 

문제 해결

우리는이 문제는 답이 생각하는 자연 참조

C (N, K) * F (NK)

F (i)는 2 개 i-th 요소 나타내고 I 세트, 임의의 개수의 세트가 교차점의 개수가 빈 형태가되도록 선택하지만, 세트 선택되지을 정당하지 않은

 

폭력 알고리즘

물론 (0) = 1 F

제공자는 g (i, j)가 세트에서의 i 번째 원소를 나타내고 K의 교점이 많은 프로그램이되도록, 임의의 개수의 세트가 선택된다

g (I, J) = C (I, J) * F (IJ)

I> 1 F (I) 용 컬렉션 -Σg = (I, J) (j≤i)

22i위한 완벽한 작품 -1

하지 컬렉션 선택한 아니지만, 참고 요소 설정된 세트 선택할 수 위치 관련 컬렉션 세트를 형성하기 위해, -1

복잡도 O (N- 2 ) 점 (70)을 원하는

 

정답 내용 斥原 관리

F (N) = Σ (-1) (N Ⅰ)을 C * (22 (NI) -1) (0≤i≤n)

ABC 에뮬레이트 집합의 A, B, C를 포함하는 교차점 집합을 나타내는

C는 (N, i)는 에뮬레이트 얼마나 많은 계산 폼 ABC의 N 세트로부터 추출 된 제 i를 나타내고

상기 소자의 i 번째 집합의 교집합이 나는 포함

의 추가 설정 한 후 임의로 선택하는 것을, 그러나 프로그램의 수는 선택되지 않습니다하지

偶加奇减,则得到全集减去这几个集合的并集,得到f(i)

 1 #include<iostream>
 2 #include<cstdio>
 3 #define ll long long
 4 using namespace std;
 5 const int mod=1e9+7;
 6 int n,k;
 7 ll js[1000010],jsinv[1000010];
 8 ll qpow(ll base,int y,int mo)
 9 {
10     ll ans=1;
11     while(y)
12     {
13         if(y&1) ans=ans*base%mo;
14         base=base*base%mo;
15         y>>=1;
16     }
17     return ans;
18 }
19 void init()
20 {
21     js[0]=1;
22     for(int i=1;i<=n;i++) js[i]=js[i-1]*i%mod;
23     jsinv[n]=qpow(js[n],mod-2,mod);
24     for(int i=n-1;i>=0;i--) jsinv[i]=jsinv[i+1]*(i+1)%mod;
25 }
26 inline ll C(int n,int m)
27 {
28     return js[n]*jsinv[m]%mod*jsinv[n-m]%mod;
29 }
30 inline ll ask(int m)
31 {
32     ll ans=0;
33     for(int i=0,u=1;i<=m;i++,u=-u)
34         ans=(ans+u*C(m,i)*(qpow(2,qpow(2,m-i,mod-1),mod)-1)%mod)%mod;
35     return ans;
36 }
37 int main()
38 {
39     scanf("%d%d",&n,&k);
40     init();
41     printf("%lld\n",(ask(n-k)*C(n,k)%mod+mod)%mod);
42     return 0;
43 }
View Code

 

 

 

另一种等价的方法

ans=C(n,k) * ∑(-1)i-k * C(n-k,i-k)*(2ˆ2ˆ(n-i) -1)        (k≤i≤n)

这种方法可以理解为固定一种组合,从其他集合中选取几个进行容斥

也能算出答案

 1 #include<iostream>
 2 #include<cstdio>
 3 #define ll long long
 4 using namespace std;
 5 const int mod=1e9+7;
 6 int n,k;
 7 ll js[1000010],jsinv[1000010];
 8 ll qpow(ll base,int y,int mo)
 9 {
10     ll ans=1;
11     while(y)
12     {
13         if(y&1) ans=ans*base%mo;
14         base=base*base%mo;
15         y>>=1;
16     }
17     return ans;
18 }
19 void init()
20 {
21     js[0]=1;
22     for(int i=1;i<=n;i++) js[i]=js[i-1]*i%mod;
23     jsinv[n]=qpow(js[n],mod-2,mod);
24     for(int i=n-1;i>=0;i--) jsinv[i]=jsinv[i+1]*(i+1)%mod;
25 }
26 inline ll C(int n,int m)
27 {
28     return js[n]*jsinv[m]%mod*jsinv[n-m]%mod;
29 }
30 int main()
31 {
32     scanf("%d%d",&n,&k);
33     init();
34     ll ans=0;
35     for(int i=k,u=1;i<=n;i++,u=-u)
36         ans=(ans+u*C(n-k,i-k)%mod*(qpow(2,qpow(2,n-i,mod-1),mod)-1)%mod)%mod;
37     printf("%lld\n",(ans*C(n,k)%mod+mod)%mod);
38     return 0;
39 }
View Code

 

 

추천

출처www.cnblogs.com/skyh/p/11117919.html