机试学习笔记07 -- 斐波那契数列、素数判定、素数筛选、二分快速幂、分解素因数、常见数学公式总结、规律神器OEIS

一、斐波那契数列

注意90项大概就会超出int范围
如果项数太大取模的话,可以参考之前的做法。
机试学习笔记07 -- 斐波那契数列、素数判定、素数筛选、二分快速幂、分解素因数、常见数学公式总结、规律神器OEIS
如果给你一个数列:a(1) = 1, a(n+1) = 1 + 1/a(n)。
那么它的通项公式为:a(n) = fib(n+1) / fib(n)。

#include<bits/stdc++.h>

using namespace std;

int f[10005] = {0};
int main(){
	int n;
	cin >> n;
	f[0] = 1, f[1] = 1;
	for(int i = 2; i <= n; ++i){
		f[i] = f[i-1] + f[i-2];
		f[i] = f[i] % 2333333;
	}
	cout << f[n] << endl;
	return 0;
}

二、素数判定

注意两点:首先,小于2的数都不是素数。其次,只用判断到根号n即可。

#include<bits/stdc++.h>

using namespace std;

bool sushu(int n){
	bool flag = 0;
	if(n == 1) return 0; //1不是素数 
	else{
		for(int i = 2; i <= sqrt(n); ++i){
			if(n % i == 0) return 0; 
		}
		return 1;
	}
}
int main(){
	int n;
	cin >> n;
	for(int i = n; ;++i){
		if(sushu(i) == 1){
			cout << i << endl;
			break;
		}
	}
	return 0;
}

三、素数筛选

用以上方法挨个判断,只能处理10000以内的数。
如下方法是线性复杂度

#include<bits/stdc++.h>

using namespace std;

//线性素数筛选,prime[0]是素数个数

const int maxn = 1000000 + 5;
int prime[maxn];
void getPrime() {  
    memset(prime, 0, sizeof(prime));  
    for (int  i = 2; i <= maxn; i++) {  
        if (!prime[i]) prime[++prime[0]] = i;  
        for (int j = 1; j <= prime[0] && prime[j] * i <= maxn; j++) {  
            prime[prime[j] * i] = 1;  
            if (i % prime[j] == 0) break;  
        }  
    }  
}  

int main(){
	getPrime();
	int a, b;
	while(cin >> a >> b){
		if(a > b) swap(a, b);
		int ans = 0;
		for(int i = 1; i <= prime[0]; ++i){
			if(prime[i] >= a && prime[i] < b){
				ans++;
			}
		}
		cout << ans << endl;
	}
	return 0;
}

四、分解素因数

前提:素因数的分解是唯一的!
1000000的素数完全够了,如果有两个素因子都大于1000000,那么这个数会大于1000000000000,超出int范围,所以数顶多只有一个超过1000000,那么只要最后当剩下一个大素因子时,把ans++即可。

#include<bits/stdc++.h>

using namespace std;

//线性素数筛选,prime[0]是素数个数,prime中其他元素是所有素数 

const int maxn = 1000000 + 5;
int prime[maxn];
void getPrime() {  
    memset(prime, 0, sizeof(prime));  
    for (int  i = 2; i <= maxn; i++) {  
        if (!prime[i]) prime[++prime[0]] = i;  
        for (int j = 1; j <= prime[0] && prime[j] * i <= maxn; j++) {  
            prime[prime[j] * i] = 1;  
            if (i % prime[j] == 0) break;  
        }  
    }  
}  

int main(){
	getPrime();
	int n;
	while(cin >> n){
		int ans = 0;
		for(int i = 1; i <= prime[0]; ++i){
			while(n % prime[i] == 0){
				n = n / prime[i];
				ans++;
			}
			if(n == 1) break;
		}
		if(n > 1) ans++; //对于大于1000000的素因子,不可能两个都大于,这样会超过范围 
		cout << ans << endl;
	} 
	return 0;
}

五、二分快速幂

有一类题目是这样的
求 (x^y) % p
当y很大的时候,我们不能直接用for去一个一个的乘,因为这样的方法复杂度是O(N)的。
可以把y分解,分解成1+2+4+8…这样翻倍。

#include<bits/stdc++.h>

using namespace std;

typedef long long int ll;

ll mod_pow(ll x, ll y, ll mod){
	ll res = 1;
	while(y > 0){
		//只有当该位为1时,去乘此时的x 
		if(y % 2 == 1) res = res * x % mod;
		x = x * x % mod;
		y = y / 2;
	}
	res = res % mod;
	return res;
}

int main(){
	ll x, n;
	cin >> x >> n;
	cout << mod_pow(x, n, 233333) << endl;
	return 0; 
}

如果x大,y也大,两步走,先大数取模,再二分快速幂。

六、常见数学公式总结

1 错排公式

问题: 十本不同的书放在书架上。现重新摆放,使每本书都不在原来放的位置。有几种摆法?
递推公式为:D(n) = (n - 1) * [D(n - 1) + D(n - 2)]
n=1时,0种;n=2时,1种;n=3时,2种。

2 海伦公式

S = sqrt(p * (p - a) * (p - b) * (p - c))
公式描述:公式中a,b,c分别为三角形三边长,p为半周长,S为三角形的面积。

3 组合数公式

机试学习笔记07 -- 斐波那契数列、素数判定、素数筛选、二分快速幂、分解素因数、常见数学公式总结、规律神器OEIS
公式描述:
组合数公式是指从n个不同元素中,任取m(m≤n)个元素并成一组,叫做从n个不同元素中取出m个元素的一个组合。

4 卡特兰数

机试学习笔记07 -- 斐波那契数列、素数判定、素数筛选、二分快速幂、分解素因数、常见数学公式总结、规律神器OEIS

七、规律神器OEIS

http://oeis.org/

上一篇:LG P3653 小清新数学题


下一篇:Prime Day 热销品出炉,看独立站如何选品?