Luogu 1031 - 均分紙牌 - [有意思的思維題]
題目連結:https://www.luogu.org/problemnew/show/P1031
題目描述
有 $N$ 堆紙牌,編號分別為 $1,2,…,N$。每堆上有若干張,但紙牌總數必為 $N$ 的倍數。可以在任一堆上取若干張紙牌,然後移動。
移牌規則為:在編號為 $1$ 堆上取的紙牌,只能移到編號為 $2$ 的堆上;在編號為 $N$ 的堆上取的紙牌,只能移到編號為 $N-1$ 的堆上;其他堆上取的紙牌,可以移到相鄰左邊或右邊的堆上。
現在要求找出一種移動方法,用最少的移動次數使每堆上紙牌數都一樣多。
例如 $N=4$,$4$堆紙牌數分別為:
①$9$ ②$8$ ③$17$ ④$6$
移動 $3$ 次可達到目的:
從 ③ 取 $4$ 張牌放到 ④ $(9,8,13,10)$ -> 從 ③ 取 $3$ 張牌放到 ② $(9,11,10,10)$ -> 從 ② 取 $1$ 張牌放到① $(10,10,10,10)$。
輸入輸出格式
輸入格式:
兩行
第一行為:$N$($N$ 堆紙牌,$1 \le N \le 100$)
第二行為:$A_1,A_2, … ,A_n$($N$堆紙牌,每堆紙牌初始數,$1 \le A_i \le 10000$)
輸出格式:
一行:即所有堆均達到相等時的最少移動次數。
輸入輸出樣例
輸入樣例#1:
4
9 8 17 6
輸出樣例#1:
3
題解:
首先,由於總牌數是 $N$ 的整數倍,因此肯定是可以有解的。每個牌堆最終的牌數就是總牌數除以堆數,設為 $k$。
其次,任意相鄰的兩個牌堆之間,最多隻進行一次移牌操作,否則就是多餘操作(這是很顯然的)。因此,不管怎麼樣,移動次數最多也就 $N-1$ 次。
那麼,如何判斷這個間隔是否需要進行移牌操作?
其實很簡單,假設這個間隔是牌堆 $i$ 和 牌堆 $i+1$ 的間隔,那麼只要前 $i$ 堆牌數之和不等於 $k \cdot i$,就要在牌堆 $i$ 和牌堆 $i+1$ 之間進行一次移牌操作。
原因也很簡單,左邊的牌數不對,右邊的牌數自然也不對,如果不在當前這個間隔移牌,就不可能讓左右兩邊的牌數變對,因此必須移牌。
AC程式碼:
#include<bits/stdc++.h> usingnamespace std; int n,k,s[105]; int main() { cin>>n; for(int i=1,x;i<=n;i++) cin>>x, s[i]=s[i-1]+x; k=s[n]/n; int ans=0; for(int i=1;i<=n;i++) if(s[i]!=k*i) ans++; cout<<ans<<endl; }