再看 唯一分解定理 UVA Choose and divide-CSDN博客

51 阅读1分钟

先用线性素数筛筛选出某一范围的素数,然后可以把若干数分解成素数相乘的多项式(大白话:小学五年级的质因子分解)。

可以解决组合数问题,避免中间数据太大无法表示的问题。

 以 UVA Choose and divide 为例\

#include <iostream>
#include <cstring>
#include <iomanip>
#include <cmath>
using namespace std;
const int N = 10000;
bool vis[N + 1];
int p[1229], cnt_p;
int getPrime(int n) {
	memset(vis, 1, sizeof vis);
	int cnt = 0;
	for (int i = 2; i <= n; ++i) {
		if(vis[i]) {
			p[cnt++] = i;
		}
		for (int j = 0; j < cnt && (i *p[j] <= n); ++j) {
			vis[i * p[j]] = 0;
			if(i % p[j] == 0) break;
		}
	} 
	return cnt;
}
int e[1229];
inline void add_integer(int n, int d) {
	//d = 1,表示乘;-1表示除
	for(int i = 0; i < cnt_p; ++i) {
		while(n % p[i] == 0) {
			n /= p[i];
			e[i] += d;
		} 
		if(n == 1) break;
	} 
} 
inline void add_factorial(int n, int d) {
	for (int i = 1; i <= n; ++i) 
		add_integer(i, d);
}

int main()
{
	int P, q, r, s;
	cnt_p = getPrime(10000); //1229
	while(cin >> P >> q >> r >> s) {
		memset(e, 0, sizeof e);
		add_factorial(P, 1);
		add_factorial(q, -1);
		add_factorial(P - q, -1);
		add_factorial(r, -1);
		add_factorial(s, 1);
		add_factorial(r - s, 1);
		double ans = 1.0;
		for (int i = 0; i < cnt_p; ++i) {
			ans *= pow(p[i], e[i]);
		}
		cout << fixed << setprecision(5) << ans << endl;
	}

	return 0;
}

\

\

UVA  Minimum Sum LCM Minimum Sum LCM

#include <iostream>
#include <cmath> 
using namespace std;
long long work(long long n, long long f[]) { //分解 
	long long cnt = 0;
	long long m = sqrt(n + 0.5);
	for (long long i = 2; i <= m && i <= n; ++i) {
		if(n % i == 0) {
			f[cnt] = i; n /= i;
			while(n % i == 0) {
				f[cnt] *= i;
				n /= i;
			}
			cnt++;
		}
	}
	if(n > 1) f[cnt++] = n;
	return cnt;
}
int main()
{
	//我对拍的都没错,一怒之下,把很多数据范围改了long long,就过了
	//可能是1e5 ~ 1e9中间哪的数据溢出了 
	long long kase = 0, n;
	while(cin >> n && n) {
		long long f[33] = {0};
		long long cnt = work(n, f);
		long long sum = 0; 
		if(cnt <= 1) sum = n + 1;
		else {
			for(long long i = 0; i < cnt; ++i)
				sum += f[i];			
		} 
		cout << "Case " << ++kase << ": " << sum << endl;		
	}

	return 0;
}


\