分金幣
阿新 • • 發佈:2019-02-10
一行 意義 NPU lld 實現 文件 答案 任務 std
看到這裏我們知道答案是所有xi的絕對值最小了
很顯然這就轉化為數軸上求一點x到\(ci\)距離和的最小值,然而這個點x其實就是序列\(ci\)(排
序後)的中位數,稍微想想應該知道
分金幣
題目描述:
? 圓桌旁坐著n個人,每人有一定數量的金幣,金幣總數能被n整除。每個人可以給他左右相鄰的人一些金幣,最終使得每個人的金幣數相等。你的任務是求出被轉手的金幣數量的最小值。比如,n=4,且4個人的金幣數分別為1,2,5,4時,只需轉移4枚金幣(第3個人給第2個人兩枚金幣,第2個人和第4個人分別給第1 個人1枚金幣)即可實現每人手中的金幣數目相等。
Input:
? 輸入包含多組數據。每組數據第一行為整數n(n<=1 000 000),以下n行每行為一個整數,按逆時針順序給出每個人擁有的金幣數。輸入結束標誌為文件結束符(EOF)。
Output:
? 對於每組數據,輸出被轉手金幣數量的最小值。輸入保證這個值在64位無符號整數範圍內。
Sample Input:
4 1 2 5 4
Sample Output:
4
題解:
假設M為每個人都擁有的金幣數,每個人的金幣變化是左右相鄰的人對其造成的影響
假設這n個人構成一個環,先假設n=4,設\(x1\)指1號給4號多少金幣,則\(x2\)代表2號給1號
多少金幣,其他的由此類推下去。
則對於1號來說,他給了4號金幣,則剩\(a1-x1\)
2號給了他金幣,則剩\(a1-x1+x2\)
註意這裏1號給4號和4號給1號的意義隱含在x1的符號裏面(很巧妙),其他的類似
由於最後要等於M,然後就可以得方程了
\(a1-x1+x2=M >> x2 = x1-(a1-M) = x1 - C1\\ a2-x2+x3=M >> x3 = x2-(a2-M)=x1-a1-a2-2*M = x1 - C2\\ a3-x3+x4=M >> x4 = x3-a1-a2-a3-3*M = x1 - C3\\ an-xn+x1=M >> xn = x1 - C(n-1)\)
看到這裏我們知道答案是所有xi的絕對值最小了
很顯然這就轉化為數軸上求一點x到\(ci\)距離和的最小值,然而這個點x其實就是序列\(ci\)(排
序後)的中位數,稍微想想應該知道
代碼:
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int maxn = 1000000+10; long long A[maxn], C[maxn], tot, M; int main(){ int n; long long sum = 0; scanf("%d", &n); for(int i = 1; i <= n; ++i){ scanf("%d", &A[i]); sum += A[i]; } int arg = sum/n; C[0] = 0; for(int i = 1; i < n; ++i){ C[i] = C[i-1] + A[i] - arg; } sort(C, C+n); long long x1 = C[n/2]; long long ans = 0; for(int i = 0; i < n; ++i){ ans += abs(x1 - C[i]); } printf("%lld\n", ans); return 0; }
分金幣