题意:输入整数n(1<=n<2^31),求至少两个正整数,使得他们的最小公倍数为n,且这些整数的和最小。输出最小的和。
分析:将n用唯一分解定理分解为n=a1^p1*a2^p2*....,不难发现每个ai^pi作为一个单独的整数时解最优,注意:n=1时,答案为1+1=2;n只有一种因子时,最优解为那个数本身加1,还要注意n=2^31-1时不要溢出。
(1) 整数的唯一分解定理:
任意正整数都有且只有一种方式写出其素因子的乘积表达式。
A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn) 其中pi均为素数
(2) 约数和公式:
对于已经分解的整数A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)
有A的所有因子之和为
S = (1+p1+p1^2+p1^3+...p1^k1) * (1+p2+p2^2+p2^3+….p2^k2) * (1+p3+ p3^3+…+ p3^k3) * .... * (1+pn+pn^2+pn^3+...pn^kn)
(3) 同余模公式:
(a+b)%m=(a%m+b%m)%m
(a*b)%m=(a%m*b%m)%m
总结大数的幂取模算法:
int pow_mod(int a,int n,int m){
int ans=1;
for(int i=0;i<n;i++) ans=(int)((long long)ans*n%m);
}
但当n很大时速度很不理想,于是采用更高效的算法:
int pow_mod(int a,int n,int m)
{
if(n==0) return 1;
int x=pow_mod(a,n/2,m);
long long ans=(long long)x*x%m;
if(n%2==1) ans=ans*a%m;
return (int)ans;
}
唯一分解算法:
1.首先要打出n以内的素数表:
void getPrimevis(int n)
{
int m=sqrt(n+0.5);
memset(vis,0,sizeof(vis));
for(int i=2; i<=m; i++)
for(int j=i*i; j<=n; j+=i) vis[j]=1;
}
然后开始唯一分解