算法学习——枚举之基于素数的代数和
算法描述
基于素数的代数和
s(n) = (1/3)-(3/5)-(5/7)+(7/9)+...+(2n-1)/(2n+1)
分子与分母中有且只有一个素数时符号取+ 分子与分母都不是素数或者都是素数,则前面的符号取-
1.求s(2016)
2.设1<=n<=2016,求当n为多大时,s(n)最大
3.设1<=n<=2016 求当n为多大时,s(n)最接近0
算法思路
-
设置一个二维数组存放数值
a[i][1]存放2i+1
a[i][0]存放0或1
如果2i+1是素数,则存放0,不为素数,则存放1
比如
a[3][1]=7
a[3][0]=1
-
当分子与分母只有一个是素数的时候,
a[i][0]+a[i+1][0]=1
,取+
,不是的话,则取-
。以此为条件,可以计算s(n)的值 -
求最大值,我们只需要在每次s(n)加或减之后进行一次判断,若s大于Max,则交换数值,第k项可以由公式
a[i][0]=2i-1
求得i,也就是k = (a[i][0]+1)/2
-
求最接近0的数值,需要判断,绝对值是否为最小,求绝对值可以使用
Math.abs(double s)
方法
算法实现
Scanner scnner = new Scanner(System.in);
int n = scnner.nextInt();
scnner.close();
int[][] a = new int[2*n+1][2];
for(int j=0,i=1;i<=2*n+1;i=i+2,j++){
if(panduan(i)){
a[j][0]=1;
}else{
a[j][0]=0; //代表i是否为素数,0不是素数,1则是素数
}
a[j][1] = i; //
}
double s =0;
int k1=1,k2=1;//第k项
double max =0,min=1;//这里min最小可以取1,或者取大于1的数字,求得最接近0的k项也是同样的
double s2=0; //存放最接近0的数值
double temp=0;//一个暂时存放数值的变量
for(int i=0;i<n;i++){
if(a[i][1]==1){
temp = (double)a[i][1]/a[i+1][1];
s =s+ temp;
}else if(a[i][0]+a[i+1][0]==1){
temp = (double)a[i][1]/a[i+1][1];
s = s +temp;
}else{
temp = (double)a[i][1]/a[i+1][1];
s = s -temp;
}
if(s>max){
max =s;
k1 = (a[i+1][1]-1)/2;
}
if(Math.abs(s)<min){
min =Math.abs(s);
s2 = s;
k2 = (a[i+1][1]-1)/2;
}
}
DecimalFormat df = new DecimalFormat("0.00000");//保留5位小数
System.out.println(df.format(s));
Max(max, k1);
Min(s2,k2);
private static void Min(double min, int k2) {
System.out.println("n为"+k2+"s最接近0");
DecimalFormat df = new DecimalFormat("0.00000");//保留5位小数
System.out.println(df.format(min));
}
private static void Max(double s,int i) {
System.out.println("n为"+i+"s最大");
DecimalFormat df = new DecimalFormat("0.00000");//保留5位小数
System.out.println(df.format(s));
}
/**
*
* @param a
* @return 判断a是否为素数
*/
public static boolean panduan(int a){
int s = (int)Math.sqrt(a);
for(int i=2;i<=s;i++){
if(a%i==0){
return false;
}
}
return true;
}