题意是,给出一个数,求以该数为最小公倍数的一组数的和的最小值。
理论基础是:唯一分解定理(也即算数基本定理)。
1.通过简单分析可以看出,这组数必须两两互质。
可以进行简单证明。设这组数只有两个数a、b,且已知题目给出lcm为M,若a、b不互质,即gcd(a,b)!=1,则lcm=a*b/gcd(a,b)!=M,假设不成立。
2.如何保证两两互质?
首先求质因子。例24=2*2*2*3=2^3*3。
其次,三个2必须在一起,即将24分解为8*3。若这三个2拆开,形成的一组数中将会出现公因子2.
进一步的分析,例如264600=8*27*25*49,分解出的这四个数是否需要对他们继续相乘、合并呢?不需要了,直接将他们加起来就是我们要的答案!为什么呢?(x/a+a>=2*sqrt(x),简单分析可知,相乘再相加的值大于直接相加。)
3.特殊值的处理
①对于1和素数,应将它分解为1乘它本身,所以和为N+1
②当所有质因子相同,例如8=2*2*2时,同样分解为1*8,和为N+1
4.时间上的优化
分解质因子时通常从1-n循环。
#include <cstdio> using namespace std; int a[10000],c,n,t; int main(){ scanf("%d",&t); //t组测试数据 while(t--){ scanf("%d",&n); c=0; for(int i=2;i<=n;i++){ while(n%i==0){ a[c++]=i; n/=i; } } for(int i=0;i<c;i++){ printf(i==0?"%d":"*%d",a[i]); } printf("\n"); } return 0; }
但事实上,对于数N,最多只有一个质因子大于sqrt(N)(简单证明,若有两个质因子a、b都大于sqrt(N),则ab相乘大于N),所以可以循环从1到sqrt(1+n).最后将大于sqrt(N)的数加上即可。
5.不同类型数值相加
long long sum; sum = (long long)n + 1;第二句代码如果不加(long long)会报错。
题目数据给到2^31-1,正好可以开到int没错,但是此时sum=2^31,要用long long。
6.对拍程序帮助debug。
AC代码:
1 #include <stdio.h> 2 #include <cmath> 3 4 using namespace std; 5 int main(){ 6 7 int n,flag,c=0,min,t; 8 long long ans; 9 while(scanf("%d",&n)&&n){ 10 ans=0;flag=0;min=sqrt(n+1); 11 for(int i=2;i<=min;i++){ 12 t=1; 13 if (n%i==0){ 14 flag++; 15 while (n%i==0) { 16 n/=i; 17 t*=i; 18 } 19 ans+=(long long)t; 20 } 21 } 22 if (flag==0) ans=(long long)n+1; 23 else if (n!=1||flag==1) ans+=n; 24 printf("Case %d: %lld\n",++c,ans); 25 } 26 return 0; 27 }