⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s2.cpp

📁 用Meisell-Lehmer算法计算PI(x)
💻 CPP
字号:
#include "stdafx.h"

typedef __int64 bint;

#include "s2.h"

#include "stdlib.h"	

#include "stdio.h"

#include "time.h"

#include "math.h"

int a;


	
pF initF(int x_13,int *PList,int *Miu)    //对结构体数组初始化的函数
{
	
	pF arrayF;              //动态开辟结构体F的数组	arrayF[x_13]

	arrayF=(pF)malloc(sizeof(F)*x_13);   //指针类型为pF

	int i,j;
	int* p;
	for(i=0;i<x_13;i++)
	{
		arrayF[i].m=i+1;           //给m赋值
		
		arrayF[i].miu_m=Miu[i];    //m相应的miu值
		
		for(p=PList,j=0;j<a;j++)   //该循环用于找m的最小质因数
		{
			if(i==0)
			{
				arrayF[i].f_m=0;
			}

			else if((i+1)%p[j]==0)
			{
				arrayF[i].f_m=p[j];

				break;
			}
		}
	}

	
	return arrayF;

}


bint max(bint x,bint y)
{
	if(x>=y)
		return x;
	else
		return y;
}
bint min(bint x,bint y)
{
	if(x>=y)
		return y;
	else
		return x;
}


int * e_sz(int l,int * m)      //提取l的二进制形式并将其二进制指数存在e_sz数组中,m同时记录数组元素个数
{
	int *e1;

	e1=(int*)malloc(sizeof(int)*32);     //整型的l最多有32位,故用长度为32的数组

	unsigned int a=2147483648;          //位运算时用的模版数

	int i,j=0;

	for(i=sizeof(int)*8-1,*m=0;i>=0;i--)
	{
		if(l&a)
		{
			e1[j]=i;
			j++;
			(*m)++;
		}
		a=a>>1;
	}
	return e1;					

}			

bint s2(bint x,int a,int *PList,int x_13,int *Miu)
{
	bint s2=0;    //函数返回值

	pF arrayF;     //算法中的F表

	arrayF=initF(x_13,PList,Miu);

	int N3;     //不整区间的长度

	double n2 = pow(x,2.0/3);
	bint N2 = (bint)(n2+0.0000001);        //精确求得x的三分之二次方取整
	bint N=x_13;       //x_13表示x的1/3次方取整

	int i,j1;//循环控制变量

	bint * fai;        
	      
	fai=(bint*)malloc(sizeof(bint)*((bint)(a+1)));
	for(i=0;i<=a;i++)
	{
		fai[i]=0;
	}                     //建立循环过程中需要使用的fai表并初始化
	
	int log2N=floor(log10(N)/log10(2))+1;        //log2N是以后反复要使用的数

	int *Ni=(int*)malloc(sizeof(int)*log2N); 
    
	for(i=0;i<log2N;i++)
	{
		Ni[i]=(N>>i)+2;
	}                               //Ni数组中也是以后反复要使用的数,这样来提速

    int * * a_sz;                   //动态建立算法中的a数组

    a_sz=(int **)malloc(sizeof(int*)*log2N);

	for(i=0;i<log2N;i++)
	{
		a_sz[i]=(int*)malloc(sizeof(int)*Ni[i]);
	}                                           
////////////////////////////////////////////////////////
	
	int*e;
	
	int l, m_e=0;

	bint**lvalue;

	lvalue=(bint**)malloc(sizeof(bint)*N);

	for(l=0;l<N;l++)                //对于每一个从1到N的l值,求得算法中的h的值,并放在lvalue数组中,这样可提速
	{
		e=e_sz(l+1,&m_e);

		lvalue[l]=(bint*)malloc(sizeof(bint)*m_e);

		for(i=0;i<m_e;i++)           //不能写for(i=0,lvalue[l][i]=1;i<N;i++)因lvalue[l][i]=1是变量
		{
			lvalue[l][i]=1;
			for(j1=0;j1<i;j1++)
				lvalue[l][i]+=(1<<(e[j1]-e[i]));
		}
		free(e);
	}

//////////////////////////////////////////////
	int**lj;
	lj=(int**)malloc(sizeof(int)*log2N);
	for(i=0;i<log2N;i++)
	{
		lj[i]=(int*)malloc(sizeof(int)*N);
		for(l=0;l<N;l++)
		{
			lj[i][l]=(l>>i)+1;
		}

	}                          //也是要反复使用的一组数,用于计算a_sz数组第二维的下标

	int *ai=(int*)malloc(sizeof(int)*log2N);   //要反复使用的一组数,用于给a_sz数组赋值

	for(i=0;i<log2N;i++)
	{
		ai[i]=1<<i;
	}

///////////////////////////////////////////////////////////

	int * eN;          //l等于N时的e数组,用于更新fai表
	int m_eN=0;
	eN=e_sz(N,&m_eN);
////////////////////////////////////////////////////////////

	int**el=(int**)malloc(sizeof(int*)*N);       //要反复使用的一组数的一组数,计算父结点时使用,可提速
	int*ml=(int*)malloc(sizeof(int)*N);
	for(l=0;l<N;l++)
	{
		el[l]=e_sz(l+1,&ml[l]);
	}

//////////////////////////////////////////////////////////
	int* p=PList;              //传入p表
	
	bint  k;                   //搜索区间参数

	bint y;                    //实际被筛到的数

	bint L,U;                  //父结点搜索区间的下限与上限

	bint m;                    //父结点
	
	bint j;                    //循环变量
	
	int notel;                 //跳跃筛选参量
	
	int delta;                 //跳跃量

	int * flag;                //表征元素y是否已被筛出过的数组

	flag=(int*)malloc(sizeof(int)*N);

 	int N2_N = N2/N;           //整区间的数目

	for(k=1;k<=N2_N;k++)       //处理第k个区间
	{	
		
//首先寻找j=0时的特殊叶子并计算其值

		L=max(ceil((x/((k*N+0.999999)*2))),1);           
		U=min((x/((((k-1)*N+1.0)*2))),N);					
		for(m=L;m<=U;m++)
		{
			if(arrayF[m-1].miu_m!=0&&arrayF[m-1].f_m>2&&m*2>N)
			{
				y=floor(x/(m*2));
				if(arrayF[m-1].miu_m==-1)
					s2+=y;
				else
					s2-=y;               //将该值累加到s2上
			}
		}              

/////////////////////////////////////////////////////////////////////////////////////////////////

		for(i=0;i<N;i++)                //初始化flag数组
			flag[i]=1;
		for(i=0;i<log2N;i++)            //初始化a_sz数组
		{
			for(j1=0;j1<Ni[i];j1++)
			{
				a_sz[i][j1]=ai[i];
			}
		}
		
//////////////////////////////////////////////////////////////////////////////////////////////////

//j不等于0时的特殊叶子的计算

		for(j=1;j<=a;j++)               //fai的第二个参数的变化
		{	
			l=PList[j-1]-((k-1)*N)%PList[j-1];      //直接计算第一个被筛出的l值

			while(l<=N&&flag[l-1]==0)
			{
				l+=PList[j-1];
			}                            //找到尚未被筛出的l值
			if(j==1)
				delta=2;
			else 
				delta=2*PList[j-1];      //跳跃量

			for(notel=l;notel<=N;notel+=delta)
			{
				if(flag[notel-1])         //当没被筛出时
				{
					for(i=0;i<log2N;i++)
					{
						a_sz[i][((notel-1)>>i)+1]--;
					}
				}
				flag[notel-1]=0;
			}                            //跳跃筛选
	
			L=max(ceil((x/((k*N+0.999999)*PList[j]))),1);
			U=min((x/((((k-1)*N+1.0)*PList[j]))),N);              //求父结点的上下限
		
			for(m=L;m<=U;m++)                           //该循环找父结点计算特殊叶子的值并累加
			{	
				if(j==a)
					break;
				
				if(arrayF[m-1].miu_m!=0 && arrayF[m-1].f_m>PList[j] && m*PList[j]>N)
				{
					y=floor(x/(m*PList[j]));
					l=y-(k-1)*N;
					bint fai_yj=0;   
					for(i=0;i<ml[l-1];i++)
					{
						fai_yj+=a_sz[el[l-1][i]][lvalue[l-1][i]];	
					}
						
					fai_yj+=fai[j];
					if(arrayF[m-1].miu_m==-1)
						s2+=fai_yj;
					else
						s2-=fai_yj;
				}
			}                                   

			bint fai_yj=0;
			for(i=0;i<m_eN;i++)
			{
				fai_yj+=a_sz[eN[i]][lvalue[N-1][i]];
			}
			fai_yj+=fai[j];
			fai[j]=fai_yj;                      //更新fai表
		}
	}
	free(eN);
	free(flag);

	for(i=0;i<log2N;i++)
		free(a_sz[i]);
	free(a_sz);
	
//////////////////////////////////////////////////////////////////////////////////////////


//以下是特殊区间的处理

	if(N3=N2-(k-1)*N)
	{	
		int log2N3=floor((log10(N3)/log10(2)))+1;      //log2N3是以后反复要使用的数

		int *N3i=(int*)malloc(sizeof(int)*log2N3);      //N3i数组中也是以后反复要使用的数,这样来提速

		for(i=0;i<log2N3;i++)
		{
			N3i[i]=(N3>>i)+2;
		}
///////////////////////////////////////////////////////////////////////////////////////////////
		a_sz=(int **)malloc(sizeof(int*)*(log2N3));     //动态建立算法中与该区间相应的a数组

		for(i=0;i<log2N3;i++)
		{	
			a_sz[i]=(int*)malloc(sizeof(int)*N3i[i]);
		}

		flag=(int*)malloc(sizeof(int)*N3);               //建立算法中与该区间相应的flag数组

//////////////////////////////////////////////////////////////////////////////////////////////////

//以下还是先求j=0时的特殊叶子的值并加至s2上

		L=max(ceil((x/((N2+0.999999)*2))),1);
		U=min((x/((((k-1)*N+1.0)*2))),N);					
		for(m=L;m<=U;m++)
		{
			if(arrayF[m-1].miu_m!=0&&arrayF[m-1].f_m>2&&(m*2)>N)
			{
				y=floor(x/(m*2));
				if(arrayF[m-1].miu_m==-1)
					s2+=y;
				else
					s2-=y;
						
			}
		}
//////////////////////////////////////////////////////////////////////////////////////////////////
		for(i=0;i<N3;i++)                  //初始化flag数组
			flag[i]=1;

		for(i=0;i<log2N3;i++)              //初始化a_sz数组
		{
			for(j1=0;j1<N3i[i];j1++)
			{
				a_sz[i][j1]=(1<<i);
			}
		}
//////////////////////////////////////////////////////////////////////////////////////////////////

//j不等于0时的特殊叶子的计算

		for(j=1;j<=a;j++)
		{	
			l=PList[j-1]-((k-1)*N)%PList[j-1];               //直接计算第一个被筛出的l值

			while(l<=N3&&flag[l-1]==0)                       //找到尚未被筛出的l值
			{
				l+=PList[j-1];
			}
			if(l>N3)
				continue;
			if(j==1)                                          //以下与整区间的处理手法同
				delta=2;
			else
				delta=2*PList[j-1];
			for(notel=l;notel<=N3;notel+=delta)
			{
				if(flag[notel-1])
				{
					for(i=0;i<log2N3;i++)
					{
						a_sz[i][((notel-1)>>i)+1]--;
					}
				}
								
				flag[notel-1]=0;
			}

			L=max(ceil((x/((N2+0.999999)*PList[j]))),1);
			U=min((x/((((k-1)*N+1.0)*PList[j]))),N);

			for(m=L;m<=U;m++)
			{
				if(j==a)
					break;
				if(arrayF[m-1].miu_m!=0&&arrayF[m-1].f_m>PList[j]&&m*PList[j]>N)//1的最小质因子怎样?
				{
					y=floor(x/(m*PList[j]));
					l=y-(k-1)*N;
					bint fai_yj=0;
					for(i=0;i<ml[l-1];i++)
					{
						fai_yj+=a_sz[el[l-1][i]][lvalue[l-1][i]];	
					}
					fai_yj+=fai[j];
					if(arrayF[m-1].miu_m==-1)
						s2+=fai_yj;
					else
						s2-=fai_yj;
				}
			}
		}
		free(flag);

		for(i=0;i<log2N3;i++)
			free(a_sz[i]);
		free(a_sz);
	}
///////////////////////////////////////////////

//所有有关数组的free
	
	free(fai);

	free(Ni);

	free(ai);

	for(i=0;i<N;i++)
	{
		free(lvalue[i]);
	}
	free(lvalue);

	for(i=0;i<log2N;i++)
	{
		free(lj[i]);
	}
	free(lj);
/////////////////////////
	for(l=0;l<N;l++)
	{
		free(el[l]);
	}
	free(el);
	free(ml);
//////////////////////////	
	return s2;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -