題意:
在的條件下,求出值最大的K個組合數
分析:
真實題意:
如何比較兩個組合數的大小?
答案是取對數然後化階乘爲前綴和,化乘除法爲加減法。
然後比較即可。
爲什麼不會爆精度???萬一第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);
}