1. 程式人生 > >NOIP2018模板總結(dalao自動忽略)【數學】

NOIP2018模板總結(dalao自動忽略)【數學】

質因數分解

//質因數分解
int prime[MAXN], tim[MAXN], cnt;
void Divide(int N)
{
	printf("%d = ", N);
	for(int i = 2; i * i <= N; i++) if(N % i == 0)
	{
		prime[++cnt] = i;
		while(N % i == 0) N /= i, tim[cnt]++;
	}
	if(N > 1) prime[++cnt] = N, tim[cnt] = 1;
	printf("%d^%d", prime[1], tim[1]);
	for(int i = 2; i <= cnt; i++)
		printf(" * %d^%d", prime[i], tim[i]);
}

線性篩素數/尤拉函式

線性篩素數/尤拉函式
int phi[MAXN], prime[MAXP], cnt;
bool vis[MAXN];
void Prime(int N)
{
	phi[1] = 1;
	for(int i = 2; i <= N; i++)
	{
		if(!vis[i]) prime[++cnt] = i, phi[i] = i-1;
		for(int j = 1; j <= cnt && i*prime[j] <= N; j++)
		{
			vis[i*prime[j]] = true;
			if(i % prime[j] == 0) { phi[i*prime[j]] = phi[i] * prime[j]; break; }
			phi[i*prime[j]] = phi[i] * (prime[j]-1);
		}
	}
}

Miller-Robin大素數測試/快速冪/快速乘

​
//Miller-Robin大素數測試
#define LL long long
//O(1)快速乘(模)
LL kmul(LL a,LL b,LL P)
{
    a = (a % P + P) % P,b = (b % P + P) % P;
    return ((a * b - (LL)((long double)a / P * b + 1e-6) * P) % P + P) % P;
}
//O(logn)快速冪
LL kpow(LL a, LL b, LL mod)
{
	LL ret = 1;
	while(b)
	{
		if(b & 1) ret = kmul(ret, a, mod);
		a = kmul(a, a, mod); b >>= 1;
	}
	return ret;
}
bool Mil_Rb(LL N, LL a)
{
	LL d = N-1; int s = 0;
	while(!(d & 1))
		d >>= 1, s++;
	LL t = kpow(a, d, N);
	if(t == 1 || t == -1) return true;
	for(int i = 0; i < s; i++)
	{
		if(t == N-1) return 1;
		t = kmul(t, t, N);
	}
	return 0;
}
bool isPrime(LL N)
{
	if(N == 2) return true;
	if(N == 1 || !(N & 1)) return false;
	LL a[5] = { 2, 3, 5, 7, 11 };
	for(int i = 0; i < 5; i++)
	{
		if(N == a[i]) return true;
		if(!(N % a[i])) return false;
		if(N > a[i] && !Mil_Rb(N, a[i])) return false;
	}
	return true;
}

​

gcd & lcm

//gcd & lcm
LL gcd(LL a, LL b) { return b ? gcd(b, a%b) : a; }
LL lcm(LL a, LL b) { return a / gcd(a, b) * b; }

exgcd

//a*x + b*y = b*y + (a%b)*x + (a/b)*b*x
//          = b*(y+x*(a/b)) + (a%b)*x
#define LL long long
void exgcd(LL a, LL b, LL &x, LL &y, LL &gcd)
{
	if(!b) { x = 1, y = 0; gcd = a; return; }
	exgcd(b, a%b, y, x, gcd); y -= x * (a/b);
}

中國剩餘定理

//中國剩餘定理
void exgcd(int a, int b, int &x, int &y)
{
	if(!b) { x = 1; y = 0; return; }
	exgcd(b, a%b, y, x); y -= x*(a/b);
}
int CRT(int *W, int *B, int k) // W > B
{
	int x, y, mulsum = 1, ans = 0;
	for(int i = 1; i <= k; i++)
		mulsum *= W[i];
	for(int i = 1; i <= k; i++)
	{
		int M = mulsum/W[i];
		exgcd(W[i], M, x, y);
		ans = (ans + y*M*B[i]) % mulsum;
	}
	if(ans < 0) ans += mulsum;
	return ans;
}

卡特蘭數 // ksm(a, mod-2)在mod為素數的情況下≡a^(-1),即a在mod下的逆元


//Catalan
const int MAXN = 5005;
int Catalan[MAXN];
int pre()
{
	Catalan[0] = 1;
	for(int i = 1; i < MAXN; i++)
		for(int j = 0; j < i; j++)
			Catalan[i] = (Catalan[i] + (LL)Catalan[j] * Catalan[i-j-1]  %mod) % mod;
	//						or
	for(int i = 1; i < MAXN; i++)
		Catalan[i] = (LL)Catalan[i-1] * (4*i-2) % mod * ksm(n+1, mod-2);
}
int Catalan(int n)
{
	return C(n<<1, n) * ksm(n+1, mod-2);
	//						or
	return (C(n<<1, n) - C(n<<1, n-1)) % mod + mod) % mod;
}