素数筛选法 O(n) O(nlgn) uva10357 选择与除法

//这个代码纯C的
#include<stdio.h> 
#include<string.h>
#include<math.h>
#define maxn 10000
int vis[maxn];
int prm[1230], e[1230];
int c, p, q, r, s;


int get_primes(int n, int *p) {
	int m = (int)sqrt(n + 0.5), i, j;
	memset(vis, 0, sizeof(vis));
	for (i = 2; i <= m; i++)
		if (!vis[i]) {
			for (j = i*i; j <= n; j += i)
				vis[j] = 1;
		}
	int c = 0;
	for (i = 2; i <= n; i++)
		if (!vis[i]) prm[c++] = i;
	return c;
}//素数筛选法 


 //乘以或除以n. d=1表示乘,d=-1表示除 
void add_integer(int n, int d) {
	int i;
	for (i = 0; i<c; i++) {
		while (n%prm[i] == 0) {
			n /= prm[i];
			e[i] += d;
		}
		if (n == 1) break;//由于无素数1,指数不会再变化了,提前终止循环,节约时间 
	}
}//最终结果分解成素数的乘积,这里改变指数 


void add_factorial(int n, int d) {
	int i;
	for (i = 1; i <= n; i++) add_integer(i, d);
}//这个阶乘并不是直接的有1乘到n,实际上,参见add_integer(); 


int main() {
	c = get_primes(maxn, prm);//c=1229
	while (~scanf("%d%d%d%d", &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;
		int i;
		for (i = 0; i<c; i++)
			ans *= pow(prm[i], e[i]);
		printf("%.5lf\n", ans);
	}
	return 0;
}

上面代码中有个函数是O(nlgn)的素数筛选法

下面这个是线性的

//O(n)线性素数筛
const int N = 10007;
bool vis[N*N]; 
int p[N]; //存素数
int getPrime(int n) {
	memset(vis, 1, sizeof vis);
	int cnt = 0; //从0开始存,若换用注释中的,则从1开始存
	for (int i = 2; i <= n; ++i) {
		if (vis[i]) {
			p[cnt++] = i;//p[++cnt] = i;
		}
		for (int j = 0; j < cnt && (i * p[j] <= n); ++j) { //j = 1; j <= cnt 
			vis[i * p[j]] = 0;
			if (i % p[j] == 0) break;
		}
	}
	return cnt; //返回2:n中素数的个数
}


素因数分解,可用于求因数的个数。


O(logn)素数判定

#include 
   
   
    
     
#include 
    
    
     
     
using namespace std; 
long long pow_mod(int a, long long d, long long mod) {
	long long res = 1, k = a;
	while(d) {
		if(d & 1) res = (res * k) % mod; 
		k = k * k % mod;
		d >>= 1;
	} 
	return res;
}
bool test(long long n, int a, long long d) {
	if(n == 2) return true;
	if(n == a) return true;
	if((n & 1) == 0) return false;
	while(!(d & 1)) d = d >> 1;
	long long t = pow_mod(a, d, n);
	while((d != n - 1) && (t != 1) && (t != n - 1)) {
		t = t * t % n;
		d <<= 1; 
	}
	return (t == n - 1 || (d & 1) == 1);
}
bool isPrime(long long n) {
	if(n < 2LL) return false;
	int a[] = {2, 3, 61};
	for (int i = 0; i <= 2; ++i) if(!test(n, a[i], n - 1)) return false;
	return true; 
} 
int main()
{
	ios::sync_with_stdio(false);
	int T;
	//for (int i = 2; i <= 100; ++i) if (isPrime(i)) cout << i << " "; //debug 
	cin >> T;
	while(T--) {
		long long num;
		cin >> num;
		cout << ((num % 2 = 0) || isPrime(num) ? 1 : 2) << endl;
	}
	
	return 0;
}
    
    
   
   




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值