判断一个数是不是素数:
bool prime(int n) { if(n==0||n==1) return false; if(n==2) return true; for(int i=2;i<=sqrt(n);i++) if(n%i==0) return false; return true; }
区间筛素数(区间内素数的个数):
#include <stdio.h> #include <cmath> #include <cstring> const int maxn = 1000001; int PrimeList[maxn]; int PrimeNum; bool IsNotPrime[maxn]; // IsNotPrime[i] = 1表示i + L这个数是素数. void SegmentPrime(int L, int U) { // 求区间[L, U]中的素数. int i, j; int SU = sqrt(1.0 * U); int d = U - L + 1; for (i = 0; i < d; i++) IsNotPrime[i] = 0; // 一开始全是素数. for (i = (L % 2 != 0); i < d; i += 2) IsNotPrime[i] = 1; // 把偶数的直接去掉. for (i = 3; i <= SU; i += 2) { if (i > L && IsNotPrime[i - L]) continue; // IsNotPrime[i - L] == 1说明i不是素数. j = (L / i) * i; // j为i的倍数,且最接近L的数. if (j < L) j += i; if (j == i) j += i; // i为素数,j = i说明j也是素数,所以直接 + i. j = j - L; for (; j < d; j += i) IsNotPrime[j] = 1; // 说明j不是素数(IsNotPrime[j - L] = 1). } if (L <= 1) IsNotPrime[1 - L] = 1; if (L <= 2) IsNotPrime[2 - L] = 0; PrimeNum = 0; for (i = 0; i < d; i++) if (!IsNotPrime[i]) PrimeList[PrimeNum++] = i + L; } int main() { int l,r; while(scanf("%d%d",&l,&r)==2) { SegmentPrime(l,r); printf("%d ",PrimeNum); } return 0; }
区间筛素数(区间内相邻的差最小和最大的素数)
#include <iostream> #include <string.h> #include <stdio.h> #include <cmath> #include <algorithm> using namespace std; const int maxn=1e6; int prime[maxn+10]; 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]<=maxn/i;j++) { prime[prime[j]*i]=1; if(i%prime[j]==0) break; } } } bool isprime[maxn+10]; int prime2[maxn+10]; void getPrime2(int L,int R) { memset(isprime,1,sizeof(isprime)); if(L<2) L=2; for(int i=1;i<=prime[0]&&(long long)prime[i]*prime[i]<=R;i++) { int s=L/prime[i]+(L%prime[i]>0); if(s==1) s=2; for(int j=s;(long long)j*prime[i]<=R;j++) if((long long)j*prime[i]>=L) isprime[j*prime[i]-L]=false; } prime2[0]=0; for(int i=0;i<=R-L;i++) if(isprime[i]) prime2[++prime2[0]]=i+L; } int main() { getPrime(); int L,R; while(scanf("%d%d",&L,&R)!=EOF) { getPrime2(L,R); if(prime2[0]<2) printf("There are no adjacent primes. "); else { int x1=0,x2=1000000,y1=0,y2=0; for(int i=1;i<prime2[0];i++) { if(prime2[i+1]-prime2[i]<x2-x1) { x1=prime2[i]; x2=prime2[i+1]; } if(prime2[i+1]-prime2[i]>y2-y1) { y1=prime2[i]; y2=prime2[i+1]; } } printf("%d,%d are closest, %d,%d are most distant. ",x1,x2,y1,y2); } } return 0; }
素数测试,若不是素数,输出它的最小素因子:
//写得太好了,每一个函数都是一个模版呀~~~~ #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #define gcc 10007 #define MAX ((INT)1<<63)-1 using namespace std; typedef unsigned long long INT; INT p[10]={2,3,5,7,11,13,17,19,23,29}; inline INT gcd(INT a,INT b) { INT m=1; if(!b) return a; while(m) { m=a%b; a=b; b=m; } return a; } //计算a*b%n inline INT multi_mod(INT a,INT b,INT mod) { INT sum=0; while(b) { if(b&1) sum=(sum+a)%mod; a=(a+a)%mod; b>>=1; } return sum; } //计算a^b%n; inline INT quickmod(INT a,INT b,INT mod) { INT sum=1; while(b) { if(b&1) sum=multi_mod(sum,a,mod); a=multi_mod(a,a,mod); b>>=1; } return sum; } bool miller_rabin(INT n) { int i,j,k=0; INT u,m,buf; //将n分解为m*2^k if(n==2) return true; if(n<2||!(n&1)) return false; m=n-1; while(!(m&1)) k++,m>>=1; for(i=0;i<9;i++) { if(p[i]>=n) return true; u=quickmod(p[i],m,n); if(u==1) continue; for(j=0;j<k;j++) { buf=multi_mod(u,u,n); if(buf==1&&u!=1&&u!=n-1) return false; u=buf; } //如果p[i]^(n-1)%n!=1那么n为合数 if(u-1) return false; } return true; } //寻找n的一个因子,该因子并不一定是最小的,所以下面要二分查找最小的那个因子 INT pollard(INT n) { INT i=1; INT x=rand()%(n-1)+1; INT y=x; INT k=2; INT d; do { i++; d=gcd(n+y-x,n); if(d>1&&d<n) return d; if(i==k) y=x,k*=2; x=(multi_mod(x,x,n)+n-gcc)%n; }while(y!=x); return n; } INT MIN; INT pollard_min(INT n) { INT p,a,b=MAX; if(n==1) return MAX; if(miller_rabin(n)) return n; p=pollard(n); a=pollard_min(p);//二分查找 INT y=n/p; b=pollard_min(y); return a<b?a:b; } int main(void) { INT T; INT n; scanf("%lld",&T); while(T--) { scanf("%lld",&n); MIN=MAX; if(miller_rabin(n)) { puts("Prime"); } else printf("%lld ",pollard_min(n)); } return 0; }