1.题目描述:题目链接
阶乘因式分解(一)
时间限制:3000 ms | 内存限制:65535 KB
难度:2
-
给定两个数m,n,其中m是一个素数。
将n(0<=n<=10000)的阶乘分解质因数,求其中有多少个m。
-
第一行是一个整数s(0<s<=100),表示测试数据的组数随后的s行, 每行有两个整数n,m。
-
输出m的个数。
-
2 100 5 16 2
样例输出
-
24 15
2.解题思路
2.1 方法一:动态规划法
输入n和m,要求n!中m的个数,n!=n*(n-1)*......*3*2*1.因此将公式展开,从1-n求解m的个数,存在求解的子问题,因此采用动态规划法。
2.2 方法二:超简单
我这个傻货只想着高级的范式能有效的提高运行效率,却没有直接看出这个问题的求解,超简单。题目要求的是n!中m的个数,既在展开式中,能对m整除才能满足条件,有很多数字直接就不能满足了。因此,整个阶乘的展开式中就那么几个满足条件的特殊数字,记为a,b,c...好了,并且他们之间是有关系的:a=n,b=a/m,c=b/m,直到我们的特殊为0为止,而结果正巧是特殊数字的和(除a外)。举个例子:a=n=100,m=5; b=a/m=20; c=b/m=4;d=c/m=0;结果result=b+c+d=243.运行代码:
自己的编程习惯和算法
我是分割线~package 语言入门; import java.util.Scanner; /* Dragon 2017.7.24 * 阶乘因式分解(一) * 方法一:用动态规划法来求解 * 运行时间199ms */ public class Num_56 { public static void main(String[] args) { Scanner in=new Scanner(System.in); //输入数据组 int number=in.nextInt(); for(int i=0;i<number;i++) { //输入n和m int n=in.nextInt(); int m=in.nextInt(); //求解m的个数并输出 int result=ZhiNumber(n,m); System.out.println(result); } } //使用动态规划的方法,求解中m的个数 private static int ZhiNumber(int n, int m) { //定义长度为n的数组,用于填表,保存的数字代表m的个数,下标从1开始 int[] flag=new int[n+1]; //让初始化的值为-1,若为0会有冲突 for(int i=1;i<=n;i++) flag[i]=-1; /* * 接下来就是对flag数组进行填数和统一求和 * 例:flag[3]表示 n!中的因数3中m的个数 * n!=1*2*3....*n 将因数都分开来填 */ //从1-n 开始填数 int i=1; int j=1; while(i<=n) { j=i; int jCount=0;//当前数字内部的计数 /* 单个数字的内部动态规划填数过程: * 数j刚进来,可以判断是否可以整除,不满足条件,flag[j]=0,此时JCount=0 * 数j被整除进来的,也如此判断,不满足条件,flag[j]=JCount,JCount已内部变化 * j满足条件,JCount变化,j整除 */ while( j%m==0 ) { //去除重复项,有值 if(flag[j] !=-1) { jCount=jCount+flag[j]; break; } //之前未计算过的 else { j=j/m; jCount++; } } flag[i]=jCount; //当前的数字求出结果,进行下一个 i++; } //统一求flag中的和值过程 int count=0; for(int p=1;p<=n;p++) count=count+flag[p]; return count; } }
参考大神后的算法提高,即法二package 语言入门; import java.util.Scanner; /* * 保留Scanner输入输出,修改算法 * 运行时间61ms */ public class my { public static void main(String[] args) { Scanner in=new Scanner(System.in); //输入数据组 int number=in.nextInt(); for(int i=0;i<number;i++) { //输入n和m int n=in.nextInt(); int m=in.nextInt(); int sum=0; //求解m的个数并输出 while(n != 0){ n /= m; sum += n; } System.out.println(sum); } } }
-
-
我是分割线~
-
-
package 语言入门; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.StringTokenizer; /* * 大神4ms的代码 */ public class 大神 { public static void main(String[] args) throws IOException{ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); int count = getInt(stdin.readLine()); int m,n,sum = 0; for(int i=0;i<count;i++) { StringTokenizer st = new StringTokenizer(stdin.readLine()); m = getInt(st.nextToken());//100 n = getInt(st.nextToken());//5 sum = 0; while(m != 0){ m /= n; sum += m; } System.out.println(sum); } } private static int getInt(String str) { return Integer.parseInt(str); } }
描述
输入
输出
样例输入