題目大意
衆所周知,LCM指最小公倍數。
令A=LCM(1~m)
B=LCM(n+1~m)
求一個最小的m使得A=B。
題解
寫這道題的時候,毫不猶豫,先敲了一個暴力,反正就算不能AC也可以找找規律,驗證猜想。
結果發現,LCM增長得非常快,即使是n=48的小數據,也跑不出來。
於是怒而找規律,看了三組樣例,以爲輸出就是n*2,結果就被出題人嘲諷了。出題人在某組答案並非n*2的數據後面加了一句:似乎不滿足規律了。
於是我就順着這個思路思考了下去。
我感覺,貌似如果這個數可以被拆分成兩個數,也就是不是質數,就應該continue掉,然後找到最早的一個質數乘2輸出。
當然這是錯的,馬上就WA了。
於是我有加了一句判斷,就是拆分成的這兩個數不能相互整除,然後就AC了。
反正我也不知道這樣是不是對的,但是我知道的是:hack數據都是
就這樣AC了,感覺是水過的呀!!!
先貼一下我的代碼,再說正解。
class MissingLCM {
public:
int getMin(int N) {
for(int i=N;i>=1;i--){
bool f=1;
for(int j=floor(sqrt(i));j>1;j--){
if(i%j==0&&i/j!=j&&i/j%j){
f=0;
break;
}
}
if(f) return i<<1;
}
return 0;
}
};
首先可以發現的一個很明顯的性質就是,答案不可能大於n*2,因爲如果m取到n*2,那麼對於1~n中的每個數都有它的兩倍,於是一定滿足A=B。正是由於這個性質,我纔想到了那種奇怪的方法。
以下都是看了題解之後的心得
可以單獨得看如何滿足每個元素。
當然這種情況,肯定是把元素拆分成素數來看,於是我們來看每一個素數。可以發現,對於一個素數的x次冪,我們只能通過把他乘二的數來保證答案是他的倍數。於是可以先把n以內的素數不斷乘自己,達到一個最大的x使得
貼一下標程吧:
vector<int> get_primes(int N)
{
// Sieve of Erathostenes to find all the necessary prime numbers:
vector<int> res;
vector<bool> composite(N + 1, false);
for (int p = 2; p <= N; p++) {
if (! composite[p]) {
for (int i = p+p; i <= N; i += p) {
composite[i] = true;
}
res.push_back(p);
}
}
return res;
}
int get_exponent(int x, int p)
{
int r = 0;
while (x % p == 0) {
r++;
x /= p;
}
return r;
}
int getMin(int N)
{
int res = 2;
// For each prime number <= N:
// 找到<=n的每個質數
for (int p: get_primes(N) ) {
// first find the maximum exponent of p among numbers <= N
// 找到p<=n的最大的冪
int max_exp = 0;
int i = p;
while (i <= N) {
max_exp = std::max(max_exp, get_exponent(i,p) );
i += p;
}
// seek the minimum i such that get_exponent(i,p) >= max_exp:
// 找到最小的i使得get_exponent(i,p)>=max_exp
while (get_exponent(i,p) < max_exp) {
i += p;
}
// the maximum for all ps is the result:
// 最大的ps是答案。
res = std::max(res, i);
}
return res;
}
順便說一句題外話,我居然在topcoder上看見一個代碼爲空的人AC了,於是我隨便交了一組數據上去,居然Challenge Successful了!什麼情況?