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

目录

一、最大乘积

解析:

全排列模板:

代码:

二、阶乘约数

解析:

唯一分解定理:

代码:

三、含2天数

解析:

Java的时间类:

代码:

四、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=2*3*3;20=2*2*5;100=2*2*5*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;
	}
}

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值