0


蓝桥冲刺31天:第九天java题解(最大乘积,阶乘约数,含2天数,K倍区间)

一、最大乘积

解析:

全排列进行运算,前置条件:乘积大于784316925;

不会全排列的可以看看下面的模板,链接中还有更多模板,好像有十来种?

全排列模板:Java【全排列 算法 模板】_山167的博客-CSDN博客_java全排列模板

public class Main {
    public static void main(String[] args) {
        int arr1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        int arr2[] = {1, 2, 3};
        f(arr1, 0);
    }
    
    //确认某一个排列的第k位
    private static void f(int[] arr, int k) {
        if (k == arr.length) {  //全部确认
        /*
            for(int x: arr) {
                System.out.print(x);
            }
            System.out.println();
        */
            //函数功能区
            return;
        }
        for (int i = k; i < arr.length; i++) { //选定第k位
            //将第i位和第k位交换
            int t = arr[i];
            arr[i] = arr[k];
            arr[k] = t;
            // 移交下一层去确认k+1位
            f(arr, k + 1);
            //回溯(换回来)
            t = arr[i];
            arr[i] = arr[k];
            arr[k] = t;
        }
    }
}

代码:

import java.util.*;
public class Main {
    static long max=0;
    static int arr[]= {1,2,3,4,5,6,7,8,9};
    static int []brr=new int[10];
    public static void main(String[] args) {
        dfs(0);
        System.out.print(max);
    }
    public static void dfs(int step) {//全排列
        if(step==9) {
            check();
            return;
        }
        for(int i=step;i<arr.length;i++)
        {
            swap(i,step);
            dfs(step+1);
            swap(i,step);
        }
    }
    public static void swap(int i,int j)
    {
        int t=arr[i];
        arr[i]=arr[j];
        arr[j]=t;
    }
    public static void check()
    {
        for(int i=0;i<=7;i++)
        {
            h(i);
        }
    }
    public static void h(int step) {
        int n1=1;
        int sum=0;
        for(int i=step;i>=0;i--)
        {
            sum+=arr[i]*n1;
            n1=n1*10;
        }
        int n=1;
        int sums=0;
        for(int i=8;i>step;i--)
        {
            sums+=arr[i]*n;
            n=n*10;
        }
        long count= (long) sum *sums;
            if(max<count) {
                if(pd(count)) {
                    max = count;
                }
            }
    }
    public static boolean pd(long s) {//判断乘积是否有1-9
        Arrays.fill(brr,0);
        while(s!=0) {
            long k=s%10;
            brr[Math.toIntExact(k)]++;
            if(brr[Math.toIntExact(k)]==2||k==0)
                return false;
            s/=10;
        }
            return true;
    }
}

二、阶乘约数

解析:

这题的话会用到一个叫《唯一分解定理》的知识

就是说:一个数可以分解为唯一的质数乘积

18=233;20=225;100=225*5;

然后去计算每一个不同质数的使用次数,每个质数+1后相乘

18:(1+1)*(2+1)=6,18有6个约数:1 2 3 6 9 18

100:(2+1)*(2+1)=9,100有9个约数:1 2 4 5 10 20 25 50 100;

这题是100以内的阶乘,我们只需要求出每一个数所拥有的的质数的总使用个数即可

唯一分解定理:

https://baike.baidu.comhttps//baike.baidu.com/item/%E7%BA%A6%E6%95%B0%E4%B8%AA%E6%95%B0%E5%AE%9A%E7%90%86/4926961

代码:

import java.math.BigInteger;

public class Main {
    public static void main(String[] args) {
        int s;
        int []arr=new int[101];
        int []brr={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
        for (int i=2;i<=100;i++) {
            s=i;
            for (int j=0;j<25;j++){
                if (s%brr[j]==0){
                    s/=brr[j];
                    arr[brr[j]]++;
                    j--;
                }
            }
        }
        BigInteger bi=new BigInteger(String.valueOf(1));
        for (int i=2;i<=100;i++){
            if (arr[i]!=0)
                bi=bi.multiply(BigInteger.valueOf(arr[i]+1));
        }
        System.out.println(bi);
    }
}

三、含2天数

解析:

时间问题,第一种枚举,一个一个循环判断,当然要注意平年和闰年(新手也能写系列)

第二种:java中有一个java.time.LocalDate;类,用这个可以直接提取时间,每一次为当前天数+1,判断是否存2即可;

Java的时间类:

代码:

import java.time.LocalDate;

public class Main {
    public static LocalDate left=LocalDate.of(1900,1,1);
    public static LocalDate right=LocalDate.of(9999,12,31);
    public static void main(String[] args) {
        int a,b,c;
        long count=0;
        while (right.compareTo(left)>=0){
            a=left.getYear();
            b=left.getMonthValue();
            c=left.getDayOfMonth();
            if (a%10==2||a/1000==2||a/10%10==2||a/100%10==2||b==2||b==12||c%10==2||c/10==2){
                count++;
            }

            left=left.plusDays(1);
        }
        System.out.println(count);
    }
}

四、K倍区间

解析:

用前缀和的方法把每一个位置和之前的位置求和,然后将每一个出现的数值统计

因为这题是k倍,所以我们可以把所有结果模k。那么最大求和数则为k-1,定义一个长度为k的数组足以存放对应数出现次数;

然后由后往前,查看该数前有多少个余数相同的求和数,则到达该数的有多少种不同的区间方案

前缀和+同余:

1 5 2 7 2
假设k=3;
1 6 8 15 17
arr[1]=1;arr[2]=6;arr[3]=8;arr[4]=15;arr[5]=17

对三取模后分别为 1 0 2 0 2
求出每一个余数出现的次数
0 : 2次
1 :1次
2 :2次

brr[0]=2,brr[1]=1;brr[2]=2;

arr[1]=1;arr[2]=0;arr[3]=2;arr[4]=0;arr[5]=2
从后往前计算出现多少次
arr[5]=2,要使为0 在它之前出现的2的次数,1次(brr[2]-1;
arr[4]为0,求它之前0的次数 1次(brr[0]-1;
arr[3]之前无2,arr[2]之前无0,arr[1]结束
次数是1+1+2(直接为0的次数)

代码:

import java.util.*;
import java.io.*;
public class Main{
    static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    static StreamTokenizer st=new StreamTokenizer(br);
    public static void main(String []age) throws Exception{
        int n=nextInt();
        int k=nextInt();
        int []arr=new int[n];
        int []brr=new int [n+1];
        int []crr=new int [k];
        for(int i=0;i<n;i++){
            arr[i]=nextInt();
            brr[i+1]=(brr[i]+arr[i])%k;
            crr[brr[i+1]]++;
    }
        long sum=crr[0];
        for(int i=n;i>=1;i--){
            crr[brr[i]]--;
            if(crr[brr[i]]>0){
                sum+=crr[brr[i]];
            }
        }
        System.out.print(sum);
    }
    public static int nextInt() throws Exception{
        st.nextToken();
        return (int)st.nval;
    }
}
标签: java 蓝桥杯 算法

本文转载自: https://blog.csdn.net/qq_55668645/article/details/123520698
版权归原作者 小怂很怂 所有, 如有侵权,请联系我们删除。

“蓝桥冲刺31天:第九天java题解(最大乘积,阶乘约数,含2天数,K倍区间)”的评论:

还没有评论