藍橋杯--求3個數的最小公倍數
細心的人不難發現,這個坑爹的藍橋杯的OJ做的如此之粗糙與惡劣,還設定了坑爹的VIP,想錢之瘋魔程度,簡直是不忍直視啊。題目上面說1~N-1, 後面給的樣例就變成的從1~N裡面篩選,這種赤裸裸的扇自己臉的行為,我只能呵呵了。
小規模吐槽完畢,接下來進入正題:
這個題的意思就是要我們在1~N的範圍內找三個數,使他們的最小公倍數在這個範圍內的組合是最大的。那麼你的第一印象是什麼的?我的第一印象是找三個兩兩互質的數,這樣只需要相乘即可,就沒有需要約分的地方。
接下來先說一個結論:大於1的兩個相鄰的自然數必定互質。
而對於1~N的範圍,肯定是 n*(n-1)*(n-2)的乘積最大、如果這三個數還兩兩互質的話那就最棒了。
如果n是奇數,那麼 n、n-1、n-2必定兩兩互質,要是有些糾結的話,那麼我們就分析在什麼情況下可能會存在公因子。n是奇數,那麼n,n-1,n-2一定是兩奇加一偶的情況。公因子2直接pass,因為只有一個偶數。假設剩下的n,n-2中有一個數能被3整除,那麼有公因子的數一定是n或n-2加減3才能得到的情況。為此,n,n-1,n-2的乘積不僅是最大的,而且一定兩兩互質。
如果n是偶數,繼續分析n*(n-1)*(n-2),這樣的話n和n-2必定有公因子2,那麼就換成式子n*(n-1)*(n-3)。然後仔細思考一下,不行啊,若偶數本身就能被3整除的話,那麼式子n*(n-1)*(n-3)也不成立了,n和n-3就有公因子3,再仔細思考一下,式子就變成了(n-1)*(n-2)*(n-3),兩奇夾一偶的情況。
程式碼如下:
- #include<iostream>
- #include<cmath>
- usingnamespace std;
- int main()
- {
- longlong n, number;
- cin>>n;
- if( n <= 2)
- {
- cout<<2;
- }
- elseif(n % 2)
- {
- number = n * (n - 1) * (n - 2);
-
cout<<number;
- }
- else
- {
- if( n % 3 == 0)
- {
- number = (n - 1) * (n - 2) * (n - 3) ;
- }
- else number = n * (n - 1) * (n - 3);
- cout<<number;
- }
- return 0;
- }
但是這個題的評測分數只給了我60分。
這個曾經讓我以為我的推論是錯誤的,後來我把程式碼改為窮舉法。
- #include<iostream>
- usingnamespace std;
- longlong gdb(longlong m, longlong n)
- {
- longlong p;
- longlong r, temp;
- if(n < m)
- {
- temp = n;
- n = m;
- m = temp;
- }
- p = n * m;
- while(m != 0)
- {
- r = n % m;
- n = m;
- m = r;
- }
- return p / n;
- }
- int main()
- {
- longlong n;
- longlong number;
- cin>>n;
- if(n <= 2)
- {
- cout<<n;
- }
- elseif(n % 2)
- {
- number = n * (n - 1) * (n - 2);
- cout<<number;
- }
- else
- {
- longlong max = 0;
- for(longlong a = n; a >= n - 10; a--)
- {
- for(longlong b = n; b >= n - 10; b--)
- {
- for(longlong c = n; c >= n - 10; c--)
- {
- number = gdb(a, gdb(b, c));
- max = max > number? max: number;
- }
- }
- }
- cout<<max;
- }
- return 0;
- }
但是窮舉法的程式碼依舊是60分,讓我很是糾結。
直到隔了一天,有一個跟我一樣糾結的人在c語言吧進行求助。c語言小吧 霧香_樓蘭 找到了原題網址。我才知道,這個收錢如流水,平臺做成渣的藍橋杯OJ,不僅抄題沒抄好,而且後臺資料都是他喵的錯的,論世上誰最坑爹,藍橋杯穩佔候選者一席。不服來辯。
大家有自己的想法就去這個網址測評這道題吧。