首页 > 其他分享 >组合数学(一本通)

组合数学(一本通)

时间:2023-05-27 17:22:20浏览次数:39  
标签:return 组合 int ll 一本 数学 long include mod

1648:【例 1】「NOIP2011」计算系数

 第一种方法:直接用杨辉三角求出二项式系数

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=1005; 
typedef long long LL;
int c[maxn][maxn];
int n,m,a,b,k;
int mod=10007;
int main(){
	cin>>a>>b>>k>>n>>m;
	for(int i=1;i<=k;i++){  //利用杨辉三角求出二项式系数 
		c[i][0]=c[i][i]=1;
		for(int j=1;j<=i-1;j++)  c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
	}
	int ans=c[k][m];
	a%=mod;b%=mod;
	int aa=1,bb=1;
	for(int i=1;i<=n;i++) aa=aa*a%mod;
	for(int j=1;j<=m;j++) bb=bb*b%mod;
	ans=ans*aa%mod*bb%mod;
	cout<<ans<<endl;
    return 0;
}

 第二种方法:用逆元破解除法取模

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=1e6+10;
const int INF=0x3fffffff;
typedef long long LL;
typedef unsigned long long ull;
//可以用杨辉三角求出当a=1,b=1时xnym的系数,其实就是C(k,n)即C(n+m,n)    如果有a,b的话,很显然就是把C(n+m,n)乘上anbm

//n+m=k  a,b<10^6
int mod=10007;
LL jc[maxn];
LL ksm(LL a,LL b){   //都记得要开LL  
	LL res=1;
	while(b){
		if(b&1){
			res=res*a%mod;
		}
		b>>=1;
		a=a*a%mod;
	}
	return res%mod;
}
//求组合数的算法
LL c(LL n,LL m){
	return jc[n]*(ksm(jc[m],mod-2)%mod)*(ksm(jc[n-m],mod-2)%mod);
} 
int main(){
	int a,b,k,n,m;
	jc[0]=jc[1]=1;
	scanf("%d %d %d %d %d",&a,&b,&k,&n,&m);
	for(int i=2;i<=k;i++){
		jc[i]=jc[i-1]*i%mod;
	}
	LL res=1;
	res=ksm(a,n)*ksm(b,m)%mod*c(n+m,n)%mod;
	printf("%lld\n",res);
return 0;
}

  

1649:【例 2】2^k 进制数

 其实根据样例分析一下也不难,主要是分类讨论,需要看最高位怎么处理,比如说样例里面,8进制的数字化为二进制至少不超过7位,那就说明了第七位只能取到1,也就是2^(w%k)-1,而数字从高位开始每一位又是递增的,所以要扣除小于首位的数字,那可以取得数字又少了。

2-len-1的第一类数:C(n,i)

len位的第二类数:for(int i=1;i<=c;i++)  C(n-i,m)       c=2^(w%k)-1

最后还要用高精度做组合数

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=282; 
const int INF=0x3fffffff;
int total[maxn];

int gcd(int a,int b){
	return b==0? a:gcd(b,a%b);
} 
void cc(int n,int m){ //求C(n,m) 
	if(n<m) return;
	int a[maxn],b[maxn]; //表示组合数的分子、分母
	for(int i=m;i>=1;i--){
		b[i]=i;   //分母  要被全部化掉 
		a[i]=n-m+i;   //分子 
	}
	for(int i=1;i<=m;i++){
		if(b[i]==1) continue; //约分  去掉分母
		for(int j=m;j>=1;j--){
			int x=gcd(b[i],a[j]);
			a[j]/=x;
			b[i]/=x;
			if(b[i]==1) break;
		} 
	}
	memset(b,0,sizeof(b)); //再拿来用
	b[1]=1;b[0]=1;
	//把约分后的分子相乘
	int jw=0;
	for(int j=1;j<=m;j++){
		jw=0;
		if(a[j]==1) continue; 
		for(int i=1;i<=b[0];i++){
			b[i]=b[i]*a[j]+jw;
			jw=b[i]/10;
			b[i]%=10;
			if(i==b[0]&&jw) b[0]++; //进位 
		}
	}
	//累加到total数组
	total[0]=max(total[0],b[0]);
	for(int i=1;i<=total[0];i++){
		total[i]+=b[i];
		total[i+1]+=total[i]/10;
		total[i]%=10;
	} 
	if(total[total[0]+1]) total[0]++;
}
int main(){
	int k,w,n,c,m;
	memset(total,0,sizeof(total)); 
	cin>>k>>w;
	n=(1<<k)-1;m=w/k;c=w%k;
	for(int i=m;i>=2;i--) cc(n,i);
	c=(1<<c)-1;
	if(c>=1&&n>m){  //还可以填剩下的位数,并且后面的数有的选,满足数组不降
		for(int i=1;i<=c;i++) cc(n-i,m); 
	}
	for(int j=total[0];j>=1;j--) cout<<total[j];
	return 0;
}

  

1650:【例 3】组合

 

 lucas定理模板题,记得开longlong

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
typedef long long ll; 
ll n,m,p;
ll ksm(ll a,ll b){
	ll s=1;
	while(b){
		if(b&1) s=s*a%p;
		a=a*a%p;
		b>>=1;
	}
	return s;
}
ll c(ll n,ll m){
	if(m>n) return 0;
	ll a=1,b=1;
	for(ll i=n-m+1;i<=n;i++) a=a*i%p;
	for(ll i=2;i<=m;i++) b=b*i%p;
	return a*ksm(b,p-2); //乘法逆元 
}
ll lucas(ll n,ll m){
	if(!m) return 1;
	else return c(n%p,m%p)*lucas(n/p,m/p)%p;
}
int main(){
	int t;
	cin>>t;
	while(t--){
		cin>>n>>m>>p;
		cout<<lucas(n,m)<<endl;
	}
	return 0;
}

  

1651:【例 4】古代猪文

这道题比较综合,会用到几个算法,首先题目不难推出结果式子 q^(sum(C(n,d)) mod q   其中d|n

首先q=999911659是个质数,q,n互质,可以由欧拉定理的推论推出 计算关键为 sum(C(n,d)) mod 9999116458 的结果

分解质因子:999911658=2*3*4679*35617,这样的数成为square-free-number ,所有质因子次数都为1

枚举n的约数d,用lucas定理计算出组合数,分别算出C(n,d)对2,3,4679,35617的模,记为a1,a2,a3,a4,然后用中国剩余定理求出线性同余方程组的解:

xmod 2=a1             xmod3=a2           xmod4679=a3     xmod35617=a4

(因为直接用lucas定理求组合数对999911658的模会超时)

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
typedef long long ll; 
const int a[4]={2,3,4679,35617};
int p[36000],b[4],mod=999911658,ans=0,n,g;
int i,j,x,y;
ll power(int a,int b){
	ll c=1;
	while(b){
		if(b&1) c=c*a%mod;
		a=(ll)a*a%mod;
		b>>=1;
	}
	return c;
}
void exgcd(int a,int b,int &x,int &y){
	if(b==0){
		x=1;y=0;return;
	}
	exgcd(b,a%b,x,y);
	int z=x;
	x=y;
	y=z-(a/b)*y;
}
int inv(int a,int p){
	int x,y;
	exgcd(a,p,x,y);
	return (x%p+p)%p;
}
int calc(int x,int mod){
	int ans=1,y,a,b;
	for(y=n;x;x/=mod,y/=mod){
		a=x%mod;b=y%mod;   //lucas定理
		ans=(ll)ans*p[b]%mod*inv(p[a],mod)%mod*inv(b<a? 0:p[b-a],mod)%mod; //把递归转为了循环 
	}
	return ans; 
}
int main(){
	cin>>n>>g;
	g%=mod+1;
	if(g==0) {
		cout<<"0"<<endl;return 0;
	}
	
	for(p[0]=i=1;i<=a[3];i++) p[i]=(ll)p[i-1]*i%mod; //阶乘
	for(i=1;i*i<=n;i++){   //枚举所有的因子   从1开始 
		if(n%i==0){
			for(j=0;j<4;j++) b[j]=(b[j]+calc(i,a[j]))%a[j];
			if(i*i!=n)
			  for(j=0;j<4;j++) b[j]=(b[j]+calc(n/i,a[j]))%a[j]; //大的因子 
		}
	}
	for(i=0;i<4;i++) {
		//中国剩余定理
		exgcd(mod/a[i],a[i],x,y);
		ans=(ans+(ll)x*(mod/a[i])%mod*b[i])%mod;
	}
	ans=(ans+mod)%mod;
	mod++;
	ans=power(g,ans);
	cout<<ans<<endl;
	return 0;
}

  

 

标签:return,组合,int,ll,一本,数学,long,include,mod
From: https://www.cnblogs.com/shirlybaby/p/17437034.html

相关文章

  • 结构型——组合模式
    推荐文档:https://www.cnblogs.com/zhili/p/DesignPatternSummery.htmlhttps://www.runoob.com/design-pattern/design-pattern-tutorial.html什么是组合模式?组合模式(CompositePattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合......
  • WPF 设置圆角窗体,通过ListView模拟下拉组合款
    界面:<Windowx:Class="WpfApp2.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.micros......
  • 数学期望DP学习笔记
    数学期望:在概率论和统计学中,数学期望(mathematicexpectation)(或均值,亦简称期望)是试验中每次可能结果的概率乘以其结果的总和,是最基本的数学特征之一。它反映随机变量平均取值的大小。——摘自百度百科不懂?太正常了,百度百科就是不写人话。举个栗子解释一下:下面看一道例题:蓝桥......
  • FLEX实践:主应用程序、MODULE、COMPONENT组合
    本次实践主要是记录下如何在FLEX主应用程序中调用一个MODULE,而在MODULE中调用COMPONENT。在开始之前先来简单谈谈MODULE这个概念 --========================================================================模块(Module)开发的优点自不待说。FlexProject中建立多个Application......
  • ZIM|一站式接入,打通 RTC 和 IM 组合拳
     从用户信息、用户心跳到用户间私人与聊天室通信,IM一直是互联网世界中不可或缺的基础建设之一。早在连麦和直播诞生之前,IM就已是在通讯领域内服役多年的老兵,而随着线上音视频的兴起,IM不仅没有没落,反而作为音视频互动的有力支撑,继续扮演着至关重要的角色。 时至今日,IM作......
  • Python解数学题
    【Python解决数学问题]用Python解方程】父亲和儿子今年共有60岁,又知4年前,父亲的年龄正好是儿子的3倍,儿子今年是多少岁?1.在Mu下载第三方库2.方程在数学中是什么方程(equation)是指含有未知数的等式。是表示两个数学式(如两个数、函数、量、运算)之间相等关系的一种等式,使等式成立......
  • 皕杰报表 + 开源可视化工具 = 实用的商业智能组合方案
    在商业智能解决方案中,数据的展现及业务规律的呈现是商业智能中及其重要的组成部分。长久以来,由于数据源复杂多样性,以及中国传统文化的对于数据表格的工整、对称等等的影响下,报表工具一直担当着商业智能的数据展现中主角的位置;最近随着显示屏技术的发展、大屏价格的下调,数据大屏及数......
  • 工程数学实验五
    (1)线性规划数学模型的建立:令x1、x2、x3分别表示种植a、b、c三种农作物的面积(单位:公顷)。目标:最大化总利润maximize:1500x1+1200x2+1800x3约束条件:劳力资源约束:450x1+600x2+900x3<=63000粪肥资源约束:35x1+25x2+30x3<=3300化肥资源约束:350x1+400x2+......
  • mysql数学和日期和加密函数
    1. 数学相关函数  762rand()返回一个随机浮点值v,范围在0到1之间(即其范围为0≤v≤1.0)。若已指定一个整数参数N.则它被用作种子值,用来产生重复序列。1.1 练习代码在E:\java学习\初级\course156\db_math#演示数学相关函数762--ABS(num)绝对值SELECTABS(-10)FROMDUAL;#......
  • 工程数学实验三
    function[x_opt,f_opt,iter]=newton_method()%定义目标函数f=@(x)100*(x(1)^2-x(2))^2+(x(1)-1)^2;%计算目标函数的梯度和Hessian矩阵grad_f=@(x)[400*x(1)*(x(1)^2-x(2))+2*(x(1)-1);-200*(x(1)^2-x(2))];hessian_f=@......