首页 > 其他分享 >P4370 [Code+#4] 组合数问题2-题解-有关对数的小技巧

P4370 [Code+#4] 组合数问题2-题解-有关对数的小技巧

时间:2023-09-27 20:48:41浏览次数:49  
标签:+# Code log int 题解 ll ans res mod

20230927

P4370 [Code+#4] 组合数问题2-sol

Statement

传送门

给你两个数 \(n,k\) , 要求对于组合数 \(C_{a}^{b}\) 找到任何 \(k\) 个, 让他们的和最大, 且组合数各不相同, 当且仅当 \(a,b\) 不完全相同时,组合数不同。

Solution

首先,很容易发现 \(C_{n}^{m}\gt c_{n-1}^{m}\),

所以我们一开始可以先把所有的 \(C_{n}^{i}\) 放到一个大根堆里面,

每一次取出堆顶 \(C_{a}^{b}\) 在把 \(C_{a-1}^{b}\) 压入即可。

但是发现 \(n\) 太大了,堆根本就没法比较。

那怎么办呢?

对于组合数,我们可以考虑取对数比较:

\[\log_2\frac{n!}{m!(n-m)!}\\=\log_2n!-\log_2m!-\log_2(n-m)! \\=\sum_{i=1}^n\log_2i-\sum_{i=1}^m\log_2i-\sum_{i=1}^{n-m}\log_2i \]

于是预处理 \(\log\) 就行了~

#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 类型)

标签:+#,Code,log,int,题解,ll,ans,res,mod
From: https://www.cnblogs.com/hwy0622/p/17734266.html

相关文章

  • SpringBoot学习4(02整合项目+前端)
    1.添加web界面在resources包下的static包中导入需要用的包,编写html。 1.1测试一下 页面控制台中成功获取数据 1.2页面显示:查询全部信息 1.3添加功能实现 新建按钮的点击事件为   @click="handleCreate()"点击新建后弹出添加页面,该页面的确定提交按钮点击事......
  • 23年9月最新微信小程序 手机号授权 (uniapp+盛派SDK) 帮你踩坑
    一、背景微信小程序手机号授权接口,从23年8月开始实行付费验证。文档地址:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getRealtimePhoneNumber.html 新版手机号授权说明如下:自2023年8月28日起【手机号实时验证组件】将需要付费使用。标准单价......
  • CF364D Ghd 题解
    CF364DGhd题解题目大意给定一个长度为\(n\)的序列,你需要从中选出一个元素个数不少于\(\left\lceil{\frac{n}{2}}\right\rceil\)的子序列,使得这个子序列中所有元素的\(\gcd\)最大。分析数据范围吓人。\(10^6\),但是根本想不到什么\(O(n\logn)\)或\(O(n)\)的算法......
  • [ARC125B] Squares 题解
    题意给定正整数\(N\),求满足如下条件的正整数对\((x,y)\)的数量:\(1\lex,y\leN\)\(x^2-y\)为完全平方数(\(0\)也是完全平方数)(\(1\leN\le10^{12}\))。题解因为\(x^2-y\)为完全平方数,设其为\(z^2\),那么有\[\begin{aligned}x^2-y=z^2\\\end{al......
  • [题解] Codeforces Round 900(Div.3) E~F
    CodeforcesRound900(Div.3)E~FE.Iva&Pav因为按位与的结果不会随着越多数字的增加而增加,因此我们可以利用这个性质二分出右端点,只需要一个可以查询区间的数据结构即可。或者是按位考虑第\(i\)个数字的第\(k\)位,后缀最近的\(0\)的位置,按位考虑也可以。但是这题使用二分......
  • 水果识别系统Python+TensorFlow+卷积神经网络算法【图像识别】
    引言随着科技的发展,我们生活中的各种便利工具日益增加。例如,你有没有想过,当你在超市里看到一个陌生的水果,却不知道它是什么名字时,有一个工具可以帮你识别出来?今天,我要为大家介绍一种基于Python的水果识别系统。这个系统不仅识别准确,还具有友好的用户界面。下面,让我们一起探索这个......
  • Effective Modern C++
     作者针对C++11/14而写的 EffectiveModernC++简介-EffectiveModernC++(cntransgroup.github.io)  一篇文章学完EffectiveModernC++:条款&实践-知乎(zhihu.com) ......
  • 每一个C++开发者都应该知道的线上工具
      每一个C++开发者都应该知道的线上工具-知乎(zhihu.com) 要想代码写得丝滑,怎么可以不熟练各种开发工具呢?锤子用的好,烦恼会减少。这里推荐几个C++开发中用于编译、构建、调试和性能分析的线上工具,最初的资料来源于LightningTalk:OnlineToolsEveryC++DevelopersSh......
  • C++(命名空间,输入输出)
    从堆上申请空间#include<malloc.h>int*p=(int)malloc(10sizeof(int));//malloc返回的是无类型free(p);//释放内存,不然会造成内存泄漏命名空间:用户自己定义的作用域namespaceN{//变量inta;//函数}inta;//不冲突命名空间可以嵌套在一个工程中,可以出现多个相同名称的命名......
  • Atcoder ABC321 笔记
    A-321-likeChecker\(\color{gray}{22}\)直接模拟voidsolve(){intn;cin>>n;intlst=-1;for(inti=n;i;i/=10){intu=i%10;if(u<=lst){cout<<"No"<<endl;......