【數學】【無話可說】[Code+#4]組合數問題2

題意:

i,jNi,j\leq N的條件下,求出值最大的K個組合數CijC_i^j


分析:

真實題意:
如何比較兩個組合數的大小?

答案是取對數然後化階乘爲前綴和,化乘除法爲加減法。

然後比較即可。

爲什麼不會爆精度???萬一第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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章