倍數問題(2018藍橋杯)
阿新 • • 發佈:2021-01-20
題目描述:
眾所周知,小蔥同學擅長計算,尤其擅長計算一個數是否是另外一個數的倍數。
但小蔥只擅長兩個數的情況,當有很多個數之後就會比較苦惱。
現在小蔥給了你 n 個數,希望你從這 n 個數中找到三個數,使得這三個數的和是 K 的倍數,且這個和最大。資料保證一定有解。
輸入格式:
從標準輸入讀入資料。 第一行包括 2 個正整數 n, K。 第二行 n 個正整數,代表給定的 n 個數。
輸出格式:
輸出到標準輸出。
輸出一行一個整數代表所求的和。
示例:
輸入: 4 3 1 2 3 4 輸出: 9
資料約定:
對於 30% 的資料,n <= 100。 對於 60% 的資料,n <= 1000。 對於另外 20% 的資料,K <= 10。 對於 100% 的資料,1 <= n <= 10^5, 1 <= K <= 10^3,給定的 n 個數均不超過 10^8。 資源約定: 峰值記憶體消耗(含虛擬機器) < 256M CPU消耗 < 1000ms 請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入...” 的多餘內容。 注意: main函式需要返回0; 只使用ANSI C/ANSI C++ 標準; 不要呼叫依賴於編譯環境或作業系統的特殊函式。 所有依賴的函式必須明確地在原始檔中 #include <xxx> 不能通過工程設定而省略常用標頭檔案。
題目分析:
本題可以使用暴力列舉,列舉分析所有的數,若分析得出結果值最大值輸出;
但是若純 暴力時間複雜度將會變得十分大,
所以可以先分析所有資料,只保留餘數相同的最大的三個數。然後逐個列舉得出結果。
程式碼:
c++:
#pragma warning(disable:4996) #include<iostream> #include<memory> #include<vector> #include<unordered_map> typedef long long ll; inline int read() { int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch>'9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } int main() { int i, num; int k, flag = 1; int b[1001][3];//用於判斷餘數相同的三個數 memset(b, -1, sizeof(b)); std::unordered_map<int, int>c;//map的key值存放餘數,value值存放餘數對應二維陣列b的下標 scanf("%d %d", &i, &num); while (i--) { k = read(); int kk = k % num; if (!c[kk]) { c[k % num] = flag;//將餘數所在的位置給map的對映 b[flag][0] = k; flag++; } else//若該餘數有值,則替換其中最小值或者加入其中 { int inte = k; for (int z = 0;z < 3;z++) if (b[c[kk]][z] < inte) inte ^= b[c[kk]][z] ^= inte ^= b[c[kk]][z]; } } //列舉 ll ans = 0, v1, v2, v3; for (auto iter1 = c.begin();iter1 != c.end();iter1++) { for (auto iter2 = c.begin();iter2 != c.end();iter2++) { int mainder = (2 * num - iter1->first - iter2->first) % num; v1 = b[iter1->second][0]; if (iter1->first == iter2->first) { v2 = b[iter1->second][1]; if (iter1->first == mainder) v3 = b[iter1->second][2]; else v3 = b[mainder][0]; if (v3 == -1 || v2 == -1) continue; } else { v2 = b[iter2->second][0]; if (iter1->first == mainder) v3 = b[iter1->second][1]; else if (iter2->first == mainder) v3 = b[iter2->second][1]; else v3 = b[mainder][0]; if (v3 == -1 || v2 == -1) continue; } ll tem = v1 + v2 + v3; if (ans < tem)ans = tem; } } printf("%lld", ans); return 0; }