梅森素数(Mersenne prime)判断, FFT 大数乘法 (非递归), O(n^2 l
|
原创代码,请勿转载! 梅森素数判定: #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<ctime>
#include<cmath>
#define EXC(a,b) a ^ b ? a ^= b ^= a ^= b : 0
#define EXCB(a,b) a > b ? a ^= b ^= a ^= b : 0
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define FORE(i,b) for(int i=(a);i<=(b);i++)
#define FORI(TYPE,it,s) for(TYPE::iterator it=s.begin();it!=s.end();it++)
#define MST(a,b) memset(a,b,sizeof(a))
#define SCF(a) scanf("%d",&a)
#define SCFS(a) scanf("%s",a)
#define SCF2(a,b) scanf("%d%d",&a,&b)
#define SCF3(a,c) scanf("%d%d%d",&b,&c)
#define min2(a,b) ((a<b)?(a):(b))
#define max2(a,b) ((a>b)?(a):(b))
#define mk(a,b) make_pair(a,b)
using namespace std;
const int INF = 0x7FFFFFFF;
const double eps = 1e-8;
const int N = 1000000+5;//1<<27;
//#define SOUT "/dev/tty"
#define SOUT "CON"
typedef unsigned long long LL;
typedef bool BB;
int add(BB a[],int na,BB b[],int nb,BB c[],bool update);
int multi(BB a[],BB c[]);
//3221225473 = 2^30 * 3 + 1,11000000000000000000000000000001
const LL MOD = 3221225473LL;
// wa#Principal 2**k-th roots of unity: w^{2^(k-1)} = -1;
const LL wa[31]={ 1LL,3221225472LL,1013946479LL,1031213943LL,2526611335LL,66931328LL,651814490LL,1292405718LL,1958494276LL,764652596LL,1855261384LL,1168849724LL,211283056LL,1734477367LL,1445148504LL,1405588668LL,2519378301LL,1800384970LL,1358427440LL,511777184LL,3009749949LL,448192265LL,3182672916LL,140749519LL,538601489LL,1838654099LL,247425463LL,229807484LL,244140625LL,15625LL,125LL};
// wb#Inverses of principal 2**k-th roots of unity: wb = wa^{-1};
const LL wb[31]={ 1LL,2207278994LL,613406496LL,741264833LL,3098715598LL,704887665LL,764521865LL,2935727869LL,2450347685LL,532203874LL,2829850173LL,1588903488LL,919321183LL,1736059882LL,3000663231LL,2793181474LL,2702431710LL,615116962LL,2055537301LL,618423934LL,762996773LL,670776757LL,2925583959LL,1181743895LL,210645833LL,1294972776LL,2980752801LL,1869040087LL,121221157LL,2267742733LL};
#define IsComp(n) (flag[n>>6]&(1<<((n>>1)&31)))
#define SetComp(n) flag[n>>6]|=(1<<((n>>1)&31))
#define MulAddMod(ans,p) ((ans + a * b) % p)
#define MulAddModZ(a,p) ((a * b) % p)
#define bits(x) ceil(log((x)+0.5)/log(2.0))
using namespace std;
unsigned int flag[(N>>6)];
LL p,IW; // prime p,2^IW = [p+p]
LL wps[N],wpr[N]; // w[i] = w^i;
LL arr[2][N]; // tmp array for calculation
BB D[N]; // tmp array for calculation
BB val[N],cont[N]; // *it:val = p*p-2,cont = -2;
// --- count prime ---
void count_Prime(int n){
int i,j;
MST(flag,0);
for (i = 3; (j = i*i) < n; i += 2)
if (!IsComp(i))
for (; j < n; j += i<<1)
SetComp(j);
}
// --- check prime ---
bool check_Prime(int x){
if(x&1){
return !IsComp(x);
}
else return (x==2);
}
// --- set w^i,n = 2^IW ---
void setw(int n,LL wt[],LL w){
wt[0] = 1;
FOR(i,1,n) wt[i] = MulAddModZ(wt[i-1],w,MOD);
}
// --- set up enviroment for Mersene Prime test ---
void setup(int _p){
p = _p;
IW = bits(p<<1);
setw(1<<IW,wps,wa[IW]);
setw(1<<IW,wpr,wb[IW]);
MST(val,0);
MST(cont,0);
//val = 4,(100),in the beginning.
val[2] = 1;
//cont = -2,(2222210),constant
FOR(i,p) cont[i] = 1;
}
// --- big integer:add() ---
int add(BB a[],bool update){
//update = true,real calcuation in multi.
//update = false,handle -2 operation.
if(na<nb) return add(b,nb,na,c,update);
bool sum,tmp,flag = 0;
int n = na;//max2(na,nb);
FOR(i,nb){
sum = a[i] ^ b[i] ^ flag;
flag = (a[i] & b[i]) | (flag & (a[i] ^ b[i]));
c[i] = sum; // in case c = a,or c = b
}
FOR(i,n){
sum = a[i] ^ flag;
flag = a[i] & flag;
c[i] = sum;
}
while(flag && update)
FOR(i,n){
sum = c[i] ^ flag;
flag = c[i] & flag;
c[i] = sum;
if(!flag) break;
}
while(n>0 && !c[n-1]) n--;
return n;
}
// --- DFT() X[] = from[] * matrix[][] ---
void DFT(int k,LL **from,LL **X,LL w[]){
// k-bit,vector size is 2^k
LL *a = *from,*b = *X;
int d,n,mask;
int u[3];//{i<<c,((i<<1)&mask)<<c,(((i<<1)|1)&mask)<<c}
for(int c = k-1;c>=0;c--){
d = 1<<(k-c);
n = 1<<c;
mask = (d-1)<<c;
FOR(i,d){
u[0] = i<<c;
u[1] = (u[0]<<1)&(mask);
u[2] = u[1] | n;
FOR(j,n) b[u[0]|j] = MulAddMod(a[u[1]|j],a[u[2]|j],w[u[0]],MOD);//w^u[0]
}
swap(a,b);
}
if(!(k&1)){
a = *from;
*from = *X;
*X = a;
}
}
// --- big integer:multi() ---
int multi(BB a[],BB c[]){ //c = a*a
int n = 1<<IW;// 2^IW >= p + p
LL *A = arr[0];
LL *C = arr[1];
FOR(i,na) A[i] = a[i];
FOR(i,n) A[i] = 0;
DFT(IW,&A,&C,wps);
FOR(i,n) A[i] = MulAddModZ(C[i],C[i],MOD);
DFT(IW,wpr);
int flag = 0;
LL cur;
FOR(i,n){
cur = C[i]>>IW;
c[i] = (cur+flag)&1;
flag = (cur+flag)>>1;
}
while(n>p){
MST(D,0);
FOR(i,p,n){
D[i-p] = c[i];
c[i] = 0; //!important
}
n = add(c,D,n-p,true);
}
for(n = p;n>0 && !c[n-1];n--);
return n;
}
// --- print array[],high bit first ---
void print(BB val[],int n){
LL ans = 0;
for(int i = n-1; i >= 0; i--){
ans = (ans << 1) + val[i];
printf("%d",val[i]);
}
printf(" -- %un",ans);
}
// --- check Mersene Prime ---
int check_Mersene(int x){
if(!check_Prime(x)) return -1;
int n = 3;//100
setup(x);
//print(val,n);
FOR(i,2,p){
n = multi(val,val);
n = add(val,cont,val,false);
// print(val,n);
}
//printf("%d # %dn",x,n);
return (!n);
}
// --- main ---
int main(int argc,char *argv[]){
count_Prime(N-1);
//check_Mersene(5);
FOR(i,3,2000){
long start = clock();
int status = check_Mersene(i);
if(status == -1){
//printf("Not a Prime %d.",i);
continue;
}
else if(status == 1){
printf("tt++++Mersenne Prime p = %d.",i);
}
else{
continue;
//printf("%d.",i);
}
cout<< "t time:" << clock()-start<<endl;
}
return 0;
}
// -----------------------------------
//freopen("in","r",stdin);
//freopen("out2","w",stdout);
(编辑:邯郸站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


