数数 2022年国赛 数论-动态规划

数数 2022年国赛 数论-动态规划_第1张图片

思路:

有一些动态规划的意思,首先得出i的素数相乘的个数为dp[i],在让i*j的相乘素数个数为dp[i*j]=dp[i]+1;j从素数列表中取出,且i%j==0时就不需要再遍历后续的素数了。因为后面i*j的结果会再次遍历的时候出现。例如:i=5x7,j=9是后续会被遇到的应该在 i=5x7,j=5时就停止。因为后面会遍历到i=7x9,j=5。所以保证要j不超过i中任意一个素数,这样就会优化将近一半的时间。

 AC代码:

import java.util.*;
public class Main{
    public static void main(String[] args) {
        //任何一个大于 1 的正整数都能被分解为若干个质数相乘,而且该分解是唯一的
        int start=2333333,end=23333333;
        int[] isPrime =new int[end+1];
        int cnt=0;
        //里面是所有的素数
        List sushu_list = new ArrayList();
        for (int i =2; i <=end; i++) {
            //类似埃氏筛 一个素数的倍数不是素数 i*j将不会被放入到素数列表sushu_list中
            if(isPrime[i]==0) {
                isPrime[i]=1;
                sushu_list.add(i);
            }
            if(i>=start&&isPrime[i]==12) cnt++;
            for (int j : sushu_list) {
                if(i*j>end) break;
                //isPrime[i*j]只会被赋值一次 因为i*j是若干个素数的积 只可能在这次中可以满足
                isPrime[i*j]=isPrime[i]+1;
                //剪枝 避免重复运算 例如 2x3x5 x 2 就不需要再继续遍历 2x3x5 x 3 了
                //因为后续还会遍历 3x3x5 x2 
                if(i%j==0) break;
            }
        }
        System.out.println(cnt);
    }
}

你可能感兴趣的:(蓝桥杯,数据结构与算法,数论,算法)