组合数

题目链接

885. 求组合数 I
886. 求组合数 II
887. 求组合数 IIIP3807 【模板】卢卡斯定理/Lucas 定理
888. 求组合数 IV

885. 求组合数 I

给定 n 组询问,每组询问给定两个整数 ab,请你输出 Cabmod(109+7) 的值。

输入格式

第一行包含整数 n

接下来 n 行,每行包含一组 ab

输出格式

n 行,每行输出一个询问的解。

数据范围

1n10000,
1ba2000

输入样例:

3 3 1 5 3 2 2

输出样例:

3 10 1

Cij=Ci1j+Ci1j1

  • 时间复杂度:O(n2)

代码

#include<bits/stdc++.h> using namespace std; const int mod=1e9+7; int c[2005][2005]; void init() { for(int i=0;i<=2000;i++) for(int j=0;j<=i;j++) if(!j)c[i][j]=1; else c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod; } int main() { init(); int n,a,b; for(scanf("%d",&n);n;n--) { scanf("%d%d",&a,&b); printf("%d\n",c[a][b]); } return 0; }

886. 求组合数 II

给定 n 组询问,每组询问给定两个整数 ab,请你输出 Cabmod(109+7) 的值。

输入格式

第一行包含整数 n

接下来 n 行,每行包含一组 ab

输出格式

n 行,每行输出一个询问的解。

数据范围

1n10000,
1ba105

输入样例:

3 3 1 5 3 2 2

输出样例:

3 10 1

Cab=a!b!(ab)!

  • 时间复杂度:O(nlog(mod))

代码

#include<bits/stdc++.h> using namespace std; const int mod=1e9+7; int n,a,b; int fac[100005],inv_fac[100005]; int ksm(int a,int b) { int res=1%mod; for(;b;b>>=1) { if(b&1)res=1ll*res*a%mod; a=1ll*a*a%mod; } return res; } void init() { fac[0]=inv_fac[0]=1; for(int i=1;i<=100000;i++)fac[i]=1ll*i*fac[i-1]%mod,inv_fac[i]=1ll*inv_fac[i-1]*ksm(i,mod-2)%mod; } int main() { init(); for(scanf("%d",&n);n;n--) { scanf("%d%d",&a,&b); printf("%d\n",1ll*fac[a]*inv_fac[b]%mod*inv_fac[a-b]%mod); } return 0; }

887. 求组合数 III

给定 n 组询问,每组询问给定三个整数 a,b,p,其中 p 是质数,请你输出 Cabmodp 的值。

输入格式

第一行包含整数 n

接下来 n 行,每行包含一组 a,b,p

输出格式

n 行,每行输出一个询问的解。

数据范围

1n20,
1ba1018,
1p105,

输入样例:

3 5 3 7 3 1 5 6 4 13

输出样例:

3 3 2
  • 时间复杂度:O(T×b×logpa×log(mod))

代码

#include<bits/stdc++.h> using namespace std; using LL=long long; int p,n; LL a,b; int ksm(int a,int b,int p) { int res=1%p; for(;b;b>>=1) { if(b&1)res=1ll*res*a%p; a=1ll*a*a%p; } return res; } inline int C(int a,int b,int p) { int res=1; for(int i=1,j=a;i<=b;i++,j--) { res=1ll*res*j%p; res=1ll*res*ksm(i,p-2,p)%p; } return res; } inline int lucas(LL a,LL b,int p) { if(a<p&&b<p)return C(a,b,p); return 1ll*C(a%p,b%p,p)*lucas(a/p,b/p,p)%p; } int main() { for(scanf("%d",&n);n;n--) { scanf("%lld%lld%d",&a,&b,&p); printf("%d\n",lucas(a,b,p)); } return 0; }

888. 求组合数 IV

输入 a,b,求 Cba 的值。

注意结果可能很大,需要使用高精度计算。

输入格式

共一行,包含两个整数 ab

输出格式

共一行,输出 Cba 的值。

数据范围

1ba5000

输入样例:

5 3

输出样例:

10

高精度乘法,阶乘分解

设素数个数为 n,每个素数平均出现次数为 m,高精度乘法复杂度 O(t)

  • 时间复杂度:O(nmt)

代码

#include<bits/stdc++.h> using namespace std; int a,b; int m,prime[5005],sum[1000]; int v[5005]; void primes(int n) { for(int i=2;i<=n;i++) { if(!v[i]) { v[i]=i; prime[++m]=i; } for(int j=1;j<=m;j++) { if(v[i]<prime[j]||i*prime[j]>n)break; v[i*prime[j]]=prime[j]; } } } inline vector<int> mul(vector<int> A,int b) { vector<int> C; int t=0; for(int i=0;i<A.size()||t;i++) { if(i<A.size())t+=A[i]*b; C.push_back(t%10); t/=10; } return C; } inline int get(int x,int p) { int res=0; while(x)res+=x/p,x/=p; return res; } int main() { scanf("%d%d",&a,&b); primes(a); for(int i=1;i<=m;i++) { int p=prime[i]; sum[i]=get(a,p)-get(b,p)-get(a-b,p); } vector<int> res(1,1); for(int i=1;i<=m;i++) for(int j=0;j<sum[i];j++) res=mul(res,prime[i]); for(int i=res.size()-1;~i;i--) printf("%d",res[i]); return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/15449611.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(107)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示