UVa 10780 - Again Prime? No Time
Description
The problem statement is very easy. Given a number n you have to determine the largest power of m, not necessarily prime, that divides n!.
Input
The input file consists of several test cases. The first line in the file is the number of cases to handle. The following lines are the cases each of which contains two integers m \((1 \lt m \lt 5000)\)
Output
For each case in the input, print the case number and result in separate lines. The result is either an integer if m divides n! or a line "Impossible to divide" (without the quotes). Check the sample input and output format.
Sample Input
2
2 10
2 100
Sample Output
Case 1:
8
Case 2:
97
Resume
對給定的數n,求出m的最大冪次,使得m的該冪次可以整除n!。
Analysis
考慮到標準分解\[ x=\prod_{i = 1}^n {{p_i} ^{\alpha_i} \quad \text{where $p_i$ is a prime number.}} \]以及指數的乘法法則,我們只需要對小於等於n的每一個數標準分解,求出每個素數對應指數之和,與m的標準分解指數作比較即可得到最大冪次。
其中需要用素數篩(線性篩)預處理素數集數組。
為了降低一點時間復雜度,還破天荒地提前讀入每一組數據做了個排序(逃。
Code
//////////////////////////////////////////////////////////////////////
//Target: UVa 10780 - Again Prime? No Time
//@Author: Pisceskkk
//Date: 2019-2-16
//////////////////////////////////////////////////////////////////////
#include<cstdio>
#include<algorithm>
#define N 10005
#define Min(a,b) (a<b?a:b)
#define Max(a,b) (a>b?a:b)
using namespace std;
int t,lm[N],ln[N],num[N],pow_m[N],pow_n[N],ans[N],max_j;
int primes[N],num_p;
bool is_prime[N];
bool comp(int a,int b){return ln[a]<ln[b];}
void sieve(int x){
num_p = 0;
is_prime[0] = is_prime[1] = 1;
for(int i=1;i<=x;i++){
if(is_prime[i] == 0){
primes[num_p++] = i;
}
for(int j=0;j<num_p && i*primes[j] <= x;j++){
is_prime[i*primes[j]] = 1;
if(i%primes[j] == 0)break;
}
}
}
int main(){
scanf("%d",&t);
for(int c=1;c<=t;c++){
scanf("%d %d",&lm[c],&ln[c]);
num[c]=c;
}
sieve(N-1);
sort(num+1,num+1+t,comp);
for(int x=1;x<=t;x++){
int m=lm[num[x]],n=ln[num[x]];
ans[num[x]] = N;
max_j = 0;
for(int i=0;i<=n;i++)pow_m[i]=0;
for(int i=ln[num[x-1]]+1;i<=n;i++){
int x = i;
for(int j=0;primes[j]<=x && j < num_p;j++){
int k=0,p=primes[j];
while(x%p == 0)p*=primes[j],k++;
x = 1ll*x*primes[j]/p;
pow_n[j]+=k;
max_j = Max(max_j,j);
}
}
for(int j=0;primes[j]<=m && j < num_p;j++){
int k=0,p=primes[j];
while(m%p == 0)p*=primes[j],k++;
pow_m[j]=k;
max_j = Max(max_j,j);
}
for(int j=0;j <= max_j;j++){
if(pow_m[j] != 0){
ans[num[x]] = Min(ans[num[x]],pow_n[j]/pow_m[j]);
}
}
}
for(int i=1;i<=t;i++){
if(ans[i]){
printf("Case %d:\n%d\n",i,ans[i]);
}
else{
printf("Case %d:\nImpossible to divide\n",i);
}
}
return 0;
}
UVa 10780 - Again Prime? No Time