1. 程式人生 > >poj2635 同餘定理 + 素數篩法

poj2635 同餘定理 + 素數篩法

      題意:給定一個數,這個數是兩個素數的乘積,並給定一個限制L,問是否兩個素數中存在小於L的數,若存在輸出較小質數,否則列印‘GOOD’。

    思路:

1 . x = a * b, a和b都是素數,那麼x只能分解為(1,x)或則(a,b),因為 x 只有四個因子1,a,b,x。

2 . 判定某大數y能否被x整除,可以通過求餘是否為0判斷。大數求餘的方法在我的上一篇文章中有證明。

3 . 素數打表,方便快速判斷某個數是否為質數。

根據第一個結論,可以知道如果某個素數(這個數小於限制L)能被大數整除,那麼這個數就是最小質數,就可以結束判斷。

AC程式碼

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 1000005;
int vis[maxn], prim[maxn], a[105];
char s[105];

int deal(int n){
	int m = sqrt(n + 0.5);
	memset(vis, 0, sizeof(vis));
	for(int i = 2; i <= m; ++i) if(!vis[i])
		for(int j = i*i; j <= n; j += i) vis[j] = 1;
		
	int cnt = 0;
	for(int i = 2; i < n; ++i){
		if(!vis[i]) prim[cnt++] = i;
	}
	return cnt;
}

// 轉換千進位制
int turn(int n){
	memset(a, 0, sizeof(a));
	int c = 0;
	int m = n % 3;
	for(int i = 0; i < m; ++i) a[c] = a[c] * 10 + s[i] - '0';
	if(m) ++c;
	for(int i = m; i < n; i += 3){
		for(int j = i; j < i + 3; ++j)
			a[c] = a[c] * 10 + s[j] - '0';
		++c;
	}
	return c;
} 

bool mod(int x, int n) {
	int m = 0;
	for(int i = 0; i < n; ++i){
		m = (m * 1000+ a[i]) % x;
	}
	if(m == 0) return true;
	return false;
}


int main(){
	int n = deal(maxn);
	int h;
	while(scanf("%s%d", s, &h) == 2 && h){
		int len = strlen(s);
		len = turn(len);
		int flag = 1;
		for(int i = 0; prim[i] < h && i < n; ++i) {
			if(mod(prim[i], len)) {
				printf("BAD %d\n", prim[i]);
				flag = 0;
				break;
			}
		}
		if(flag) printf("GOOD\n");
	}
	return 0;
}

如有不當之處歡迎指出!