Codeforces Round #493 (Div. 2) (A B C D)
A. Balloons
題目大意:讓你把所有的氣球分成兩份,使得兩份的數量不同,隨便分。
解題思路:用一個結構體存數量和序號,在根據數量排個序,對於n<=2進行特判下,對於n>2的情況直接輸出1和第一個數的序號即可。
AC程式碼:
B. Cuttingstruct node { int x; int id; }e[15]; bool cmp(node a, node b) { return a.x < b.x; } int main() { int n, a[20]; while(~scanf("%d", &n)) { for(int i = 0; i < n; i ++) { scanf("%d", &e[i].x); e[i].id = i+1; } sort(e, e+n, cmp); if(n <= 1) { printf("-1\n"); continue; } if(n == 2) { if(e[0].x == e[1].x) printf("-1\n"); else printf("1\n1\n"); continue; } printf("1\n%d\n", e[0].id); } return 0; }
題目大意:給你一個數組,讓你把他分成幾塊,使得每塊的奇數個數和偶數個數相同,每次分的花費為分開處兩邊數字差的絕對值,讓你求出在花費不超過B的情況下,能分幾下。
解題思路:先求出奇數和偶數個數的字首和,然後按照字首和的個數把所有能分的地方的花費都算出來,再排個序,從小到大取,直到大於B,最後輸出次數。
AC程式碼:
C. Convert to Onesint main() { int n, b, a[110], sum1[110], sum2[110]; while(~scanf("%d%d", &n, &b)) { mem0(sum1); mem0(sum2); for(int i = 1; i <= n; i ++) { scanf("%d", &a[i]); if(a[i]&1) { sum1[i] = sum1[i-1] + 1; sum2[i] = sum2[i-1]; }else { sum1[i] = sum1[i-1]; sum2[i] = sum2[i-1] + 1; } } int cost[110], sum = 0; for(int i = 1; i < n; i ++) { if(sum1[i] == sum2[i] && sum1[n] - sum1[i] == sum2[n] - sum2[i]) { cost[sum ++] = abs(a[i] - a[i+1]); } } sort(cost, cost+sum); int ans = 0, s = 0; for(int i = 0; i < sum; i ++) { s += cost[i]; if(s <= b) { ans ++; }else break; } printf("%d\n", ans); } return 0; }
題目大意:給你一個字串,有兩種操作,花費x把一段字串反轉,花費y把一段連續的0都變成1,求出把該字串全都變成1的最小花費。
解題思路:先求出0塊區域的數量為sum,如果沒有反轉的操作,那麼就需要進行sum次變換的操作,有了反轉這個操作,模擬下你會發現,每一次反轉操作都只會減少一個0塊,所以就相當與一次反轉操作可以代替一次變換的操作,這樣這個問題就成了一個貪心的問題:當x<y時,就儘量多進行反轉,也就是反轉sum-1次,最後進行一次變換的操作即可,如果x>=y時,就都進行變換的操作。
AC程式碼:
D. Roman Digitsint main() { int n; LL x, y; char str[300010]; while(~scanf("%d%lld%lld", &n, &x, &y)) { scanf("%s", str); LL sum = 0; for(int i = 0; i < n-1; i ++) { if(str[i] == '0' && str[i+1] == '1') sum ++; } if(str[n-1] == '0') sum ++; if(sum == 0) printf("0\n"); else if(y <= x) { printf("%I64d\n", sum*y); }else { printf("%I64d\n",x*(sum-1) + y); } } return 0; }
題目大意:給你4個數1 5 10 50,讓你挑n個數相加,每個數可以選任意次數,求出能算出多少種不同的數字。
解題思路:%彪神一波,思路數彪神給的:對於這種型別的題,一看資料範圍這麼大,然後又沒有取模的操作,對於每個樣例又是出入輸出的型別,那麼肯定是打表找規律的題,或者可能是什麼結論或著公式題之類的,也許這就是題目做多了後,自然又得題感吧,看來還是要多刷題啊!切入正題,我們先dfs跑一邊結果,看看有沒有什麼聯絡,果然在n<=11時並沒有什麼聯絡,但是當n>12時,結果就是一個公差為49的等差數列,那麼我們對n<=11的結果進行打表,後面的不斷加49即可。
AC程式碼:
LL a[12] = {
4,
10,
20,
35,
56,
83,
116,
155,
198,
244,
292
};
int main()
{
LL n;
while(~scanf("%I64d", &n)) {
if(n <= 11) {
printf("%I64d\n", a[n-1]);
}else {
printf("%I64d\n", a[10] + 49*(n-11));
}
}
return 0;
}