蓝桥杯算法基础(32):素数,埃式筛法,快速幂,斐波那契与矩阵幂运算

素数

有些人认为一个人一生中有三个周期,从他或她出生的那一天开始。
这三个周期是身体周期,情感周期的和智力的周期,他们有周期的长度为23,28,
和33天。每一个周期都有一个高峰。在一个周期的高峰期,
一个人在他/她在相应的领域(身体,情绪或精神)。
例如,如果它是心理曲线,思维过程会更清晰和集中会更容易。
由于三个周期有不同的周期,所以这三个周期的峰值一般发生在不同的时间。
我们想确定何时发生绝对高潮(所有三个周期的峰值发生在同一天)。
因为处于绝对高潮时人各方面均表现优异,因此人们想知道绝对高潮在哪一天出现。
对身体周期,情绪周期和智力周期,给出本年内他们各自的一个高潮日(不一定是第一个)后经过的天数p,e,i。另外,给出本年内已经经过的天数d(d>=0).求出在d所代表的日期多少天后,
三种周期的高潮日又一次在同一天出现。


输入:输入数据有多组,每组测试数据占一行,有四个整数,p,e,i和d.  p,e,i 分别代表从0开始计时,身体周期,情感周期和智力周期首次出现高潮的日期,要求编程计算经过d后多少天第一个绝对高潮出现,输入保证绝对高潮在21252内的某一天出现。输入以-1,-1,-1结束。

输出:例如:Case 1: the next triple peak occurs in 1234 days.


23 28 33
d1 d2 d3

d1+23k1=x
d2+28k2=x
d3+33k3=x

x≡d1 %23
 ≡d2 %28
 ≡d3 %33



//延续上体的解题方法
//逐级合并法
x=a1(%m1)
 =a2(%m2)
 =a3(%m3)
x=a1+m1y1 (1)
x=a2+m2y2
==>m1y1-m2y2=a2-a1这是一个线性方程可解出y1  linearEquation(m1,m2,a2-a1)
    带回(1).得特解x0=a1+m1*y1-->x=x0+k*lcm(m1,m2)得一个新方程//lcm(m1,m2),m1,m2得公倍数
    x≡x0 (%lcm(m1,m2))
    形成新的a(x0),新的m(lcm(m1,m2))

public static void main(String[] args)throws Exceeption{

        Scanner sc= new Scanner(System.in);
        int t=1;
        List<long[]> aList=new ArrayList<long[]>();
        List<long> dList=new ArrayList<long>();

        while(sc.hasNext()){

            long[] a={sc.nextLong(),sc.nextLong(),sc.Long()};
            long d=sc.nextLong();
            if(a[0]==-1&&a[1]==-1&&a[2]=-1&&d==-1)break;
            else{
            aList.add(a);
            aList.add(d);
            }

        }

   for(int i=0;i<aList.size();i++){
    long[] a=aList.get(i);
    long d=dList.get(i);
    long[] m={23,28,33};

    long res=Case05_ExtGcd.linearEquationGroup(a,m);
    while(res<=d){
    res+=21252;//保证在21252内,就是以21252为模
    }

        System.out.println("Case"+(t++)+": the next triple peak occurs in"+(res-d)+"days");

   }

}

埃式筛法

public static void mian(){
        long now=System.currentTimeMillis();
        m1(100000);
        System.out.println(”耗时“+(System.currentTimeMillis()-now)+"ms" );
}

private static void  m1(int N){
        //N是第N个素数
        //已知在整数X内大概有x/log(X)个素数
        //现在我们要逆推,要想求第N个素数,我们的整数范围是社么
        //length就是整数范围

        int n=2;
        while(n/log(n)<N){//n个数中,大概有n/log(n)个素数
        n++;
        }
        //开辟一个数组,下标是自然数,值是标记
        //基本思路是筛选法,把非素数标记出来
        //int[] arr=new int[n];
        int x=2;
        while(x<n){
               //标记过了。继续下一个
               if(arr[x]!=0){
               continue;
               }

               int k=2;
               //对每个x,我们都从2倍开始,对x的k倍,全部标记-1
               while(x*k<n){
                  arr[x*k]=-1;
                  k++;
               }

               x++;


        }

        //System.out,println(arr);

        //筛完之后,这个很长的数组里面非素数下标对应的值都是-1
        int sum=0;

          for(int i=2;i<arr.length;i++){
            //是素数,计数+1
            if(arr[i]==0){
              sum++;
            }

            if(sum==N){
            System.out,println(i);
            }

          }
}

 快速幂

反复平方
a^10    8 0 2 0
        1 0 1 0
a^(2^3) a^(2^2) a^(2^1) a^(a^0);

将次方转成二进制,哪一位有1,就乘以那一位所在的a的平方值
如 a^10=a^(2^3)*a(2^1)

public static long ex2(long n,long m){
    long primeFangShu = n;//n的1次方
    long result=1;
    while(m!=0){
        if((m&1)==1){
        result*=pingFangShu;
        //每移位一次,幂累成方一次
        pingFangShu=pingFangShu*pingFangShu;
        //无论等不等于1,次方都成倍乘

        //右移一位
        m>>=1;
        }
        return result;

    }

}

 斐波那契与矩阵幂运算

(f1.f2)=(1,1)

(f1,f2)*[0 1]=[f2.f3] //0+1=1=f1,1+1=2=f3=f1+f2
        [1 1]

(f1.f2)*[0 1]^2=[f3,f4]
        [1 1]

....递推

[f1,f2]*[0 1]^n-1=[fn,fn+1]
        [1 1]


public static long fib(long n){
        if(n==1||n==2)return1;
        long[][] matrix={
            {0,1},
            {1,1}
        };

        long[][] res=Util.matrixPower(matrix,n-1);//矩阵的乘方
        res=Util.matrixMultiply(new long[][]{(1,1)},res);//矩阵的乘方与f1f2相乘
        return res[0][0];

}

public long[][] matrixPower(long[][] matrix,long p){


//初始化结果为单位矩阵,对角线为1
long[][] result=new long[matrix.length][matrix[0].length];
//单位矩阵。相当于整数的1
    for(int i=0;i<result.length;i++){
    result[i][i]=1;
    }

   //平方数
long[][] pingFang=matrix;//一次方

for(;p!=0;p++){
   while(p!=0){
        if((p&1)!=0){//当前二进制最低位1,将当前平方数乘到结果中
        result=matrixMultiply(result,pingFang);

        }
        平方数继续上翻
        pinFang=matrixMultiply(pingFang,pingFang);
        p>>1;
    }

    return result;
}

}

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-30 07:48:04       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-30 07:48:04       106 阅读
  3. 在Django里面运行非项目文件

    2024-03-30 07:48:04       87 阅读
  4. Python语言-面向对象

    2024-03-30 07:48:04       96 阅读

热门阅读

  1. VUE——mixins混入

    2024-03-30 07:48:04       42 阅读
  2. 如何避免公网IP安全风险

    2024-03-30 07:48:04       41 阅读
  3. MongoDB聚合运算符:$last

    2024-03-30 07:48:04       44 阅读
  4. Linux内网提权

    2024-03-30 07:48:04       44 阅读
  5. 机器学习:scikit-learn库的主要组件

    2024-03-30 07:48:04       39 阅读
  6. Leetcode 15. 三数之和

    2024-03-30 07:48:04       39 阅读
  7. 美团二面极差体验

    2024-03-30 07:48:04       40 阅读
  8. 接口和抽象类有什么区别?

    2024-03-30 07:48:04       39 阅读
  9. 实现公网数据传输给内网(使用frp)

    2024-03-30 07:48:04       41 阅读
  10. DM Mysql Oracle 日期函数 dameng

    2024-03-30 07:48:04       37 阅读
  11. 学生管理系统本地化存储版

    2024-03-30 07:48:04       45 阅读
  12. Redis Scan指令解析与使用示例

    2024-03-30 07:48:04       43 阅读
  13. MongoDB聚合运算符:$linearFill

    2024-03-30 07:48:04       37 阅读