题目描述
知识点
质因子分解
结果
实现
码前思考
- 由于这道题目出现在质因子分解的章节里面,所以我能想到要往质因子分解这条道上走,但是要是没有这个提示我可能很难想到!我可能还会想动态规划,哈哈哈哈哈。
- 首先,题中说
N
小于等于1000,那么如果直接暴力求解N!
肯定会超出long long
范围,所以我们要另辟蹊径,而最好的方法就是分解问题! - 我们都知道
N! = N * (N-1) (N-2) * ... * 2
。其次每个数都可以转换成质因子的乘积,所以我们在N!
和a
之间找到了它们的公共部分——质因子! - 因此,我们只要比较
N!
的质因子是否包含 a k a^k ak的质因子就可以判断是否整除了。
代码实现
//直接暴力是不可以的,因为n!会特别大
//正是因为特别大,所以我们要另辟蹊径
//而最好的方法就是分解问题!
//我们使用质因子分解,将n!分解成质因子的乘积
//然后把a也进行分解,这样就可以解题啦
#include "bits/stdc++.h"
using namespace std;
const int maxn = 1010;
int prime[maxn];
int pNum = 0;
bool p[maxn]={0};
int n;
int a;
unordered_map<int,int> mpN;
unordered_map<int,int> mpA;
void Find_Prime(){
for(int i=2;i<maxn;i++){
if(p[i] == false){
prime[pNum++] = i;
for(int j=i+i;j<maxn;j=j+2){
p[j] = true;
}
}
}
}
int main(){
//打表质数
Find_Prime();
while(~(scanf("%d",&n))){
scanf("%d",&a);
//共享数据结构处理
mpN.clear();
mpA.clear();
//寻找n!的质因子,也就是n,n-1,n-2,...,2的质因子
for(int i=2;i<=n;i++){
int num = i;
int sqr = (int)sqrt(1.0*num)+1;
for(int j=0;prime[j]<=sqr;j++){
while(num % prime[j] == 0){
mpN[prime[j]]++;
num = num / prime[j];
}
}
if(num != 1){
mpN[num]++;
}
}
// for(unordered_map<int,int>::iterator it=mpN.begin();it!=mpN.end();it++){
// int p = it->first;
// int cnt = it->second;
// printf("%d %d\n",p,cnt);
// }
//寻找a的质因子
int sqr = (int)sqrt(1.0*a)+1;
for(int j=0;prime[j]<=sqr;j++){
while(a % prime[j] == 0){
mpA[prime[j]]++;
a = a / prime[j];
}
}
if(a != 1){
mpA[a]++;
}
// for(unordered_map<int,int>::iterator it=mpA.begin();it!=mpA.end();it++){
// int p = it->first;
// int cnt = it->second;
// printf("%d %d\n",p,cnt);
// }
//接下来求k
int flag = true;
int k = 0;
for(;flag == true;k++){
for(unordered_map<int,int>::iterator it=mpA.begin();it!=mpA.end();it++){
int p = it->first;
int cnt = it->second;
if(cnt*k > mpN[p]){
// printf("%d\n",p);
// printf("%d\n",cnt*k);
flag = false;
break;
}
}
}
printf("%d\n",k-2);
}
return 0;
}
码后反思
- 这里使用
unordered_map
不用结构体存储质因子,会更加省心一些; - 复习了一下
unordered_map
的一些基本操作~~ - 依然是质因子分解三步走战略!
- 《王道》上面的解法和我的不同。我感觉自己的这个时间复杂度更高一些。但是我不想看那个了,头痛!