1. 程式人生 > 實用技巧 >UVA10791 最小公倍數的最小和 Minimum Sum LCM

UVA10791 最小公倍數的最小和 Minimum Sum LCM

[https://www.luogu.com.cn/problem/UVA10791]

sol:
設唯一分解式\(n = p_1^{a_1}p_2^{a_2}...\),那麼\(p_i^{a_i}\)作為一個單獨的整數時最優。
證明一下,對於一個合數x, 將它們拆成兩個互質的數a和b,答案會更優,可以用作差法證明。其次,對於n,我們不能將單獨的一個 $p_i^{a_i} $ 拆開, 因為要保證最小公倍數為n,所以
拆出來的數中 \(p_i\) 的指數的最大值要為 \(a_i\).

注意特判n=1與分解式中只有一個質數的情況。

#include <iostream>
#include <cstring>
#include <iostream>
using namespace std;

typedef long long LL;

const int N = 1500;
int p[N], val[N], a[N], pos;

void divide(LL n) {
   for(LL i = 2; i * i <= n; i ++) {
   	if( n % i == 0) {
   		int cnt = 0;
   		++ pos;
   		val[pos] = 1;
   		while(n % i == 0) {
   			n /= i;
   			cnt ++;
   			val[pos] *= i;
   		}
   		a[pos] = cnt;
   		p[pos] = i;
   	}
   }
   if(n > 1) {
   	p[++ pos] = n;
   	a[pos] = 1;
   	val[pos] = n;
   }
/*	for(int i = 1; i <= pos; i ++) {
   	printf("%d^%d ", p[i], a[i]);
   }
   puts("");*/
}

int main() {
   LL n;
   int T = 0;
   while( scanf("%lld", &n) == 1 && n) {
   	pos = 0;
   	divide(n);
   	LL ans = 0;
   	if( n == 1) {
   		ans = 2;
   	}
   	else if( pos == 1) {
   		ans = (LL)(val[1] + 1ll);
   	}
   	else {
   		for(int i = 1; i <= pos; i ++) {
   			ans += val[i];
   		}
   	}
   	printf("Case %d: %lld\n", ++T, ans);
   }
   return 0;
}