0
点赞
收藏
分享

微信扫一扫

蓝桥杯_数学知识_3 (高斯消元【解方程】- 求组合数【C(a,b)】- *卡特兰数*)

您好 2022-04-06 阅读 34

文章目录

高斯消元 - 解方程 [暂且不管-需进一步优化]





//bug~~~~~~~~~~~~~~~~~~~~~~
#include <iostream>
using namespace std;
#include<cmath>
#include<algorithm> 

const int N = 110;
int n;
double a[N][N]; 
const double eps =  1e-6 ;

int gauss()
{
	int c,r;
	for(c = 0,r = 0;c < n;c ++)
	{
		int t = r;
		for(int i = r;i < n;i ++)
			if(fabs(a[i][c]) > fabs(a[t][c]))
				t = i;
		
		if(fabs(a[t][c]) < eps) continue;
		
			for(int i = c;i <= n;i++)swap(a[t][i],a[r][i]);
			for(int i = n;i >= c;i--)a[r][i] /= a[r][c];
			for(int i = r + 1;i < n;i++)
				if(fabs(a[i][c]) > eps ) 
					for(int j = n;i >= c;j--)
					a[i][j] -= a[r][j] * a[i][c]; //系数乘上得值,减去等于0,说明解是正确的 
				
		r ++ ;
	}
	
	if(r < n)
	{
		for(int i = r;i < n;i ++)
			if(fabs(a[i][n]) > eps)  // 0 = 非零 的情况 
				return 2;//无解	
			return 1; //否则有无穷多组解	
	}
	
	for(int i = n - 1;i >= 0;i --)
		 for(int j  = i + 1;j < n;j++)
		 	a[i][n] -= a[i][j] * a[i][n]; 
	
	return 0;//有唯一解 
	
}

int test_01()
{
	cin >> n;
	for(int i = 0;i < n;i++)
		for(int j = 0;j < n + 1;j ++)
			cin >> a[i][j];
	
	int t = gauss();
	if(t == 0)
	{
		for(int i = 0;i < n;i ++) printf("%.2lf",a[i][n]); //题目保留两位小数 
	}
	else if(t == 1) puts("Infinte group solutions");//唯一解 
	else puts("No solution"); //无解 
	return 0;
}

885. 求组合数 I C(m,n)



const int N = 2010 , mod = 1e9 + 7;
int c[N][N];

void init()
{
	for(int i = 0;i < N;i ++)
		for(int j = 0;j <= i;j ++)
		if(!j) c[i][j] = 1; //定义: C(b,0) = 1 
		else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1] % mod);	//DP 选/不选 
} 

int test_02()
{
	init();
	
	int n;
	scanf("%d",&n);
	while(n --)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		printf("%d\n",c[a][b]);
	}
	
	return 0;
}


886 求组合数 II 【数据大小10万级别】 【费马小定理+快速幂+逆元】



typedef long long LL;
const int N = 100010,mod = 1e9 + 7;

int fact[N],infact[N]; 

int qmi(int a,int k,int p) //数值大就LL 一般都是!!! 
{
	int res = 1; //乘除法的初始值 
	while(k)
	{
	if(k % 2) res = (LL)res * a % p; //强转      也可以k & 1 表示奇数就行 
	a = (LL)a * a % p;
	k >>= 1;
	}
	
	return res; 
}

int test_03()
{
	fact[0] = infact[0] = 1; //乘除法的初始值 
	for(int i = 1;i < N;i++)
	{
		fact[i] = (LL)fact[i - 1] * i % mod;//i的阶乘 
		infact[i] = (LL)infact[i - 1] * qmi(i,mod - 2,mod) % mod; //a % p 的逆元 的幂 = p-2 ,a逆为a^p-2^ 
	}
	
	int n;
	scanf("%d",&n);
	while(n --)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		printf("%d\n",(LL)fact[a] * infact[b] % mod * infact[a - b] % mod);  //%f等于0原因分母求解过程中0,后一直为0,最后相乘结果为0 
	}
	
	return 0;
}

887. 求组合数 III 【le18级别】 【卢卡斯定理 + 逆元 + 快速幂 】





#include<algorithm>

typedef long long LL;
int p;

int qmi(int a,int k) //p是全局变量不用传进来,直接用 
{
	int res = 1;
	while(k)
	{
		if(k % 2) res = (LL)res * a % p;
		a = (LL)a * a % p; 
		k >>= 1;
	}

	return res;
}
//特别注意题目给定输入的a,b顺序 
int C(int a,int b)  //组合数 C(a,b)  == b! / (a-b)! * a!      ******** 
{
	int res = 1;
	for(int i = 1,j = a ;i <= b;i++,j--) // i为b!  ,j = a!  ,qmi求i逆元 为  
	{
		res = (LL)res * j % p; //除 , 乘上i的逆元 
		res = (LL)res * qmi(i,p-2) % p; 
	}
	return res;
}

int lucas(LL a,LL b) //递归    //传进的数是LL类型 
{
	if(a < p && b <p) return C(a,b);
	return (LL)C(a % p,b % p) * lucas(a / p, b / p) % p;
}

int test_04()
{
	int n;
	cin >> n;
	while(n --)
	{
		LL a, b;
		cin >> a >> b >> p ;
		cout << lucas(a,b) << endl; 
	}
}

888.求组合数 IV 【没有%p – 高精度算出准确结果】 【分解质因数 + 高精度乘法 --只用一次高精度提高运行效率】





#include<vector>
const int N = 5010;

int primes[N],cnt;
bool st[N]; 
int sum[N];

void get_primes(int n) //线性筛法啊 
{
	for(int i = 2;i <= n;i++)
	{
		if(!st[i]) primes[cnt ++] = i;//没有标记,需遍历i的质数的倍数 ,筛除 [第一次i为2,是质数先放入,后面3,5同理,4就被筛掉了]
		for(int j = 0 ;primes[j] <= n / i;j++) //遍历到 i == sqrt(n)  
		{
			st[primes[j] * i] = true; //筛除i的质数的倍数, 
			if(i % primes[j] == 0) break; // i是pj 的倍数时,后面已经筛选完了,都是倍数,就不用继续了,结束 
		}
	}
}

int get(int n,int p) //质因数的个数 
{
	int res = 0;
	while(n)
	{
		res += n / p;
		n /= p;
	}
	return res;
}

vector<int> mul(vector<int> a,int b)
{
	vector<int> c;
	int t = 0;
	for(int i = 0;i < a.size();i++)
	{
		t += a[i] * b;
		c.push_back(t % 10);
		t /= 10;
	}
	
	while(t)//t == 0结束 
	{
		c.push_back( t % 10);
		t /= 10;	
	}	
	
	return c;
}

int test_05()
{
	int a,b;
	cin >> a >> b;
	get_primes(a);
		
	for(int i = 0;i < cnt;i++)
	{
		int p = primes[i];
		sum[i] = get(a,p) - get(b,p) - get(a - b,p);
	}
	
	vector<int> res;
	res.push_back(1); 
	
	for(int i = 0;i < cnt;i++)
		for(int j = 0;j < sum[i];j++)
			res = mul(res,primes[i]); // res * primes[i]
	
	for(int i = res.size() - 1;i >= 0;i --) printf("%d", res[i]);
	puts("");
	
	return 0;
} 

889 满足条件的01序列 【卡特兰数-用法极多!】




typedef long long LL;
const int mod = 1e9 + 7;

int qmi(int a,int k,int p)  //如果p不是质数,那么逆元只能用扩展欧几里得定理求!!! 
{
	int res = 1;
	while(k)
	{
		if(k % 2) res = (LL)res * a % p;
		a = (LL)a * a % p;
		k >>= 1; 
	}
	
	return res;
}

int test_06()
{
	int n;
	cin >> n;
	
	int a = 2 * n , b = n;
	int res = 1;
	//求C(2*n,n) 
	for(int i = a;i > a - b;i --) res = (LL)res * i % mod; 
	for(int i = 1;i <= b;i ++) res = (LL)res * qmi(i,mod - 2,mod) % mod; 
	
	res = (LL)res * qmi(n + 1,mod - 2,mod) % mod;
	
	cout << res << endl;
	
	return 0;
}


int main() {
	
	test_06(); 
	
	return 0;
}


举报

相关推荐

0 条评论