[CP1804]组合数问题2

题目大意:
  给定两个数$n(n\le10^6)$和$k(k\le10^5)$,找到$k$个不同的满足$0\le b\le a\le n$的组合数$\binom a b$,求这$k$个组合数的最大值。

思路:
  显然对于同一个$a$,$b=\lfloor\frac a 2\rfloor$时组合数取到最大值,可以先对于所有的$0\le a\le n$求出$b=\lfloor\frac a 2\rfloor$时的组合数的值,用一个堆来维护。取走这个数同时把$a$相同的,仅次于它的组合数加入堆,比较时为避免精度问题用对数比较。时间复杂度$O(n\log n)$。

 1 #include<queue>
 2 #include<cmath>
 3 #include<cstdio>
 4 #include<cctype>
 5 typedef long long int64;
 6 inline int getint() {
 7     register char ch;
 8     while(!isdigit(ch=getchar()));
 9     register int x=ch^'0';
10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
11     return x;
12 }
13 const int N=1e6+1,mod=1e9+7;
14 int fact[N],factinv[N];
15 void exgcd(const int &a,const int &b,int &x,int &y) {
16     if(!b) {
17         x=1,y=0;
18         return;
19     }
20     exgcd(b,a%b,y,x);
21     y-=a/b*x;
22 }
23 inline int inv(const int &x) {
24     int ret,tmp;
25     exgcd(x,mod,ret,tmp);
26     return (ret%mod+mod)%mod;
27 }
28 inline int calc(const int &a,const int &b) {
29     return (int64)fact[a]*factinv[b]%mod*factinv[a-b]%mod;
30 }
31 struct Node {
32     long double val;
33     int a,b,d;
34     bool operator < (const Node &another) const {
35         return val<another.val;
36     }
37 };
38 std::priority_queue<Node> q;
39 int main() {
40     const int n=getint(),k=getint();
41     for(register int i=fact[0]=1;i<=n;i++) {
42         fact[i]=(int64)fact[i-1]*i%mod;
43     }
44     factinv[n]=inv(fact[n]);
45     for(register int i=n;i;i--) {
46         factinv[i-1]=(int64)factinv[i]*i%mod;
47     }
48     for(register int a=0;a<=n;a++) {
49         if(a&1) {
50             q.push((Node){lgamma(a+1)-lgamma(a/2+1)-lgamma(a-a/2+1),a,a/2,-1});
51             q.push((Node){lgamma(a+1)-lgamma(a/2+2)-lgamma(a-a/2),a,a/2+1,1});
52         } else {
53             q.push((Node){lgamma(a+1)-lgamma(a/2+1)-lgamma(a-a/2+1),a,a/2,0});
54         }
55     }
56     int ans=0;
57     for(register int cnt=0;cnt<k;cnt++) {
58         int a=q.top().a,b=q.top().b,d=q.top().d;q.pop();
59         (ans+=calc(a,b))%=mod;
60         if(d!=1&&b!=1) q.push((Node){lgamma(a+1)-lgamma(b)-lgamma(a-b+2),a,b-1,-1});
61         if(d!=-1&&b!=a) q.push((Node){lgamma(a+1)-lgamma(b+2)-lgamma(a-b),a,b+1,1});
62     }
63     printf("%d\n",ans);
64     return 0;
65 } 

 

posted @ 2018-04-02 20:34  skylee03  阅读(124)  评论(0编辑  收藏  举报