阶乘 题解
阶乘
https://ac.nowcoder.com/acm/contest/5505/C
题目为: 给定一个正整数 p
求一个最小的正整数 n,使得 n! 是 p 的倍数
求一个最小的正整数 n,使得 n! 是 p 的倍数
大家是否还记得我们初高中学习的一个东西叫做质因数,就比如说6中的质因数为2和3,因为2*3等于6,其中6当中只有1个2和一个3,而8中有3个2组成为2*2*2=8;
所以要找到n,就必须使阶乘n中的大于对应p中所有质因数的个数。就比如4!中有7个2,就比8中的三个2多,4!就可以是8的倍数。
首先我们要求出p中质因数的种类以及每种种类的个数;我定义了一个f函数来完成,注意如果for完p还是>1的话,记得记录一下这个质因数。
然后用二分查找最小的那个n符合n!是p的倍数。
最关键的来了,有些小伙伴可能会问了,怎样检查n!是p的倍数呢?我在这用了一个check函数。
这是最关键性的代码了.
public static boolean check(int n)
{
int nums=0;
int x=n;
for(int i=1;i<=k;i++)
{
x=n;
nums=0;
while(x>0)
{
nums+=x/zhiyin[i];
x/=zhiyin[i];
}
if(zhiyinshu[i]>nums)
return false;
}
return true;
} 乍一看可能会看不太懂,这里我给大家举一个例子. 比如我们寻找8!中有多少个2.
因为8/2=4 4/2=2 2/2=1 所以8!当中有4+2+1=7个2,不信大家可以自己计算一下,8中有3个2,6中有1个2,4中有2个2,2中有1个2,3+1+2+1=7.
是不是感觉很神奇,这里相关问题还是不明白的话就询问度娘吧。
然后我们可以检查一下p质因数每个种类的个数是否小于等于对应n!中质因数的个数,全部都小于等于的话就符合条件啦,如果有一个大于的话当然就要返回false了。
代码如下
import java.math.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.*;
public class Main {
public static int zhiyin[] = new int[10000];
public static int zhiyinshu[] = new int[10000];
public static int k;
public static void main(String args[])throws IOException
{
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
in.nextToken();
int T = (int)in.nval;
int n,a,b;
for(int t=0;t<T;t++)
{
in.nextToken();
n = (int)in.nval;
Arrays.fill(zhiyin,0);
Arrays.fill(zhiyinshu,0);
out.println(f(n));
out.flush();
}
}
public static int f(int n)
{
k=0;
int N=n;
for(int i=2;i*i<=n;i++)
{
if(n%i==0)
{
zhiyin[++k] = i;
while(n%i==0)
{
zhiyinshu[k]++;
n/=i;
}
}
}
if(n>1)
{
zhiyin[++k] = n;
zhiyinshu[k]++;
}
int l=1,r=1000000009,mid,min=0;
while(l<=r)
{
mid = (l+r)>>1;
if(check(mid)==true)
{
min = mid;
r = mid-1;
}
else{
l = mid+1;
}
}
return min;
}
public static boolean check(int n)
{
int nums=0;
int x=n;
for(int i=1;i<=k;i++)
{
x=n;
nums=0;
while(x>0)
{
nums+=x/zhiyin[i];
x/=zhiyin[i];
}
if(zhiyinshu[i]>nums)
return false;
}
return true;
}
}
查看20道真题和解析
