CodeForces Round 224 B (二分或圖論) C (等差數列 水題)
阿新 • • 發佈:2019-01-23
昨天的 B 題的確有點意思.....
他的題目很含蓄 .... 給你 A 和 C ,C 每秒減 1 ,A 的話給你三個數 b, x, w, 若 b >= x ,b = b - x,否則 a = a - 1, b = w - (x - b)(每秒只完成一個分支)。後面那個式子展開後就發現不管在 if 的哪個分支裡面,b 都是減去 x 的,只是當 b < 0 的時候要加上個 w,所以 k 次操作之後 b 變成了 b - k * x + n * w,n 是讓這個式子大於 0 的最小值。
a = a - k, c = c - n
然後二分答案就可以了。
圖論的話是這樣,因為 b 的範圍是小於 1000 的,可以列舉 b 的可能的數值,然後建立一個狀態轉移的圖,找到迴圈節,然後搞啊搞,這種方法好麻煩,到最後的時候還要判斷最後一秒的時候是否有用。因為當操作 c - 1 的時候, a 也減了 1,這樣就不減少差值,若之前相等的話還要對答案減一。
二分= =,額。
#include<stdio.h> #include<cmath> #include<iostream> using namespace std; #define LL long long LL a,b,w,x,c; bool OK(LL k) { LL n=(k*x-b)/w; if((k*x-b)%w) n++; if(k-n>=c-a) return true; return false; } int main() { cin>>a>>b>>w>>x>>c; LL ub=1e13,lb=-1; if(c<=a) { puts("0"); return 0; } while(ub-lb>1) { LL m=(ub+lb)>>1; if(OK(m)) ub=m; else lb=m; } cout<<ub<<endl; }
C 嘛,就是給你 n 個數,讓你判斷有幾個位置可以使得這個數列加一個數之後變成等差數列。
分開考慮。1 和 2 的時候比較特殊,1 可以有無數個, 2 最多可以有三個, 剩下的要麼是 2 個,要麼是 1 個。
最後,要考慮差是 0 的特殊情況,因為這樣的話原來可以放兩個數的位置, 因為相同就變成一個數了。
#include<stdio.h> #include<iostream> #include<algorithm> #include<vector> using namespace std; #define LL long long LL num[100009]; struct myD { LL pos; LL cnt; LL w; }dd[2]; int main() { int n ; scanf("%d", &n); for(int i = 0; i < n; i++) cin >> num[i]; if(n == 1) { printf("-1"); return 0; } sort(num, num + n); if(n == 2) { LL d = abs(num[1] - num[0]); if(d == 0) { puts("1"); printf("%d\n", num[0]); return 0; } if(d == 1 || d % 2) { cout << 2 << endl << num[0] - d << " "<< num[1] + d; return 0; } cout << 3 << endl << num[0] - d << " " << num[0] + (d / 2) << " " << num[1] + d << endl; return 0; } dd[0].w = dd[1].w = -1; dd[0].cnt = dd[1].cnt = 0; for(int i = 0; i < n - 1; i++) { LL d = num[i + 1] - num[i]; if(d == dd[0].w || dd[0].w == -1) { dd[0].cnt++; dd[0].pos = i; dd[0].w = d; }else if(d == dd[1].w || dd[1].w == -1) { dd[1].cnt++; dd[1].pos = i; dd[1].w = d; }else { cout << 0 << endl; return 0; } } myD * small, *more; small = dd[0].w < dd[1].w ? &dd[0] : &dd[1]; more = dd[0].w > dd[1].w ? &dd[0] : &dd[1]; if(small->w == -1) { if(more->w == 0) { cout << 1 << endl <<num[0]; return 0; } puts("2"); cout << num[0] - more->w << " " << num[n - 1] + more->w << endl; return 0; } if(more->cnt != 1 || small->w ==0 ||more->w % 2 || more->w / small->w != 2) { puts("0"); return 0; } puts("1"); cout << num[more->pos] + small->w << endl; return 0; }