P4370 [Code+#4] 组合数问题2-题解-有关对数的小技巧
20230927
P4370 [Code+#4] 组合数问题2-sol
Statement
给你两个数
Solution
首先,很容易发现
所以我们一开始可以先把所有的
每一次取出堆顶
但是发现
那怎么办呢?
对于组合数,我们可以考虑取对数比较:
于是预处理
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e6+5;
const ll mod=1e9+7;
ll jc[N],inv[N],ans=0;
double lg[N];
int n,k;
priority_queue<pair<double,pair<int,int> > > q;
ll qpow(ll a,ll b){
ll res=1ll;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
void init(){
jc[0]=1ll;
for(int i=1;i<=n;i++) jc[i]=1ll*jc[i-1]*i%mod;
inv[n]=qpow(jc[n],mod-2);
for(int i=n;i>=1;i--) inv[i-1]=1ll*inv[i]*i%mod;
for(int i=1;i<=n;i++) lg[i]=lg[i-1]+1ll*log(i);
}
double find(int a,int b){
return lg[b]-lg[a]-lg[b-a];
}
ll getans(int a,int b){
return jc[b]*inv[a]%mod*inv[b-a]%mod;
}
int main(){
/*2023.9.27 H_W_Y P4370 [Code+#4] 组合数问题2 堆*/
scanf("%d%d",&n,&k);init();
for(int i=n;i>=1;i--) q.push({find(i,n),{i,n}});
while(k--){
int a=q.top().second.first;
int b=q.top().second.second;
q.pop();
ans=(ans+getans(a,b))%mod;
q.push({find(a,b-1),{a,b-1}});
}
printf("%lld\n",ans);
return 0;
}
Conclusion
对于数字太大无法比较的情况,我们可以考虑用对数去比较(double 类型)
本文作者:H_W_Y
本文链接:https://www.cnblogs.com/H-W-Y/p/17734266.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步