【数学】【无话可说】[Code+#4]组合数问题2

题意:

i , j ≤ N i,j\leq N i,jN的条件下,求出值最大的K个组合数 C i j C_i^j Cij


分析:

真实题意:
如何比较两个组合数的大小?

答案是取对数然后化阶乘为前缀和,化乘除法为加减法。

然后比较即可。

为什么不会爆精度???万一第K大数和第K+1大数,数值极大又极其接近,那不就爆了吗???为什么连long double都不用就能卡过去???

出题人真有意思。表示无F***可说

#include<cstdio>
#include<cstring>
#include<cmath>
#include<set>
#include<queue>
#include<algorithm>
#define SF scanf
#define PF printf
#define MAXN 1000010
#define MOD 1000000007
using namespace std;
typedef long long ll;
ll fac[MAXN],inv[MAXN];
double dfac[MAXN];
ll fsp(ll x,ll y){
    ll res=1;
    while(y){
        if(y&1ll)
            res=res*x%MOD;
        x=x*x%MOD;
        y>>=1ll;
    }
    return res;
}
double Cd[510][510];
struct node{
    int n,m;
    double res;
    node () {}
    node (int n1,int m1):n(n1),m(m1) {}
    bool operator <(const node &a) const{
        return dfac[n]-dfac[m]-dfac[n-m]<dfac[a.n]-dfac[a.m]-dfac[a.n-a.m];
    }
};
set<pair<int,int> >used;
priority_queue<node>q;
int n,m;
void prepare(){
    fac[0]=1;
    for(int i=1;i<=n;i++)
        fac[i]=fac[i-1]*i%MOD;
    inv[n]=fsp(fac[n],MOD-2);
    for(int i=n;i>0;i--)
        inv[i-1]=inv[i]*i%MOD;
    for(int i=1;i<=n;i++)
        dfac[i]=dfac[i-1]+log(i);
    
}
ll C(int x,int y){
    return fac[x]*inv[y]%MOD*inv[x-y]%MOD;	
}
int main(){
    SF("%d%d",&n,&m);
    prepare();
    for(int i=0;i<=n;i++)
        q.push(node(n,i));
    ll ans=0;
    while(m--){
        int x=q.top().n;
        int y=q.top().m;
        q.pop();
//		PF("[%d %d]",x,y);
        (ans+=C(x,y))%=MOD;
        used.insert(make_pair(x,y));
        if(y>=0&&used.count(make_pair(x,y-1)))
            q.push(node(x-1,y-1));
        if(x-1>=y&&used.count(make_pair(x,y+1)))
            q.push(node(x-1,y));
    }
    PF("%lld",ans);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值