题目描述
计算能被小于等于n 的正整数整除的最小正整数是多少
答案对 1000000007
求模.
数据格式
输入格式
一行输入一个整数 n
输出格式
输出符合题意的最小整除数
样例
输入数据
10
输出数据
2520
思路分析:
已知该题要求能被从1到n的所有数字整除的最小数字,也就是求这些数的最小公倍数,求最小公倍数的方法有两种:
- 公式法
由于两个数的乘积等于这两个数的最大公约数与最小公倍数的积。即(a,b)×[a,b]=a×b。所以,求两个数的最小公倍数,就可以先求出它们的最大公约数,然后用上述公式求出它们的最小公倍数。
but原题给出的数据范围是105,求105个数的最大公约数是不可取的,那还有第二个方法
2.分解质因数法
先把这几个数的质因数写出来,最小公倍数等于它们所有的质因数的乘积(如果有几个质因数相同,则比较两数中哪个数有该质因数的个数较多,乘较多的次数)。
总结一下就是求出对于每个数字分解质因数后每个只因数取最高次然后求乘积.
copy:
#include<bits/stdc++.h>
using namespace std;
long long n,a=1;
unordered_map<long long ,long long >m,m0,m1;
int main(){
cin>>n;
for(long long j=n;j>=2;j--){
long long jj=j;
for (long long i = 2; i*i <= j; i++){
if (jj % i == 0){
m1[i]=m1[i]+1;
if(m[i]<m1[i])m[i]=m1[i];
jj/=i;
i--;
}
}
//cout<<jj<<endl;
if(jj!=0){m1[jj]=m1[jj]+1;
if(m[jj]<m1[jj])m[jj]=m1[jj];}
//for(auto& i : m1)cout<<j<<":"<<i.first<<":"<<i.second<<endl;
m1=m0;
}
for(auto& i : m){
a=a%1000000007;
a*=(long long)pow(i.first,i.second)%1000000007;
a=a%1000000007;
}
cout<<a;
return 0;
}
接下来分解一下代码:
- 准备部分
#include<bits/stdc++.h>
using namespace std;
long long n,a=1;
unordered_map<long long ,long long >m,m0,m1;
这里
解释一下各个map的作用,m是存最高次的,m0是负责还原m1的,m1是负责存储从1到n每个数分解质因数过程中的幂次数的
- 分解从1到n每个数的质因数
for(long long j=n;j>=2;j--){
long long jj=j;
for (long long i = 2; i*i <= j; i++){
if (jj % i == 0){
m1[i]=m1[i]+1;
if(m[i]<m1[i])m[i]=m1[i];
jj/=i;
i--;
}
}
if(jj!=0){m1[jj]=m1[jj]+1;
if(m[jj]<m1[jj])m[jj]=m1[jj];}
m1=m0;
}
这里有一个300分的悲惨故事,也就是在分解时循环到了n,后来改成i*i <= n居然也得到了400分,不得不说这个数据有点弱,正确的循环应该是 i*i <= j
- 相乘求积
for(auto& i : m){
a=a%1000000007;
a*=(long long)pow(i.first,i.second)%1000000007;
a=a%1000000007;
}