还是要多写些有点儿技术含量的东西 @.@~
题目大意是,N个人(N<=1000)围成一圈,给定每个人需要的酒杯数。每
次侍者必须同时拿上或拿下距离为K(1<=K<=N)的两个杯子。问侍者最少
需要拿多少次才能满足要求,并输出侍者拿杯子的方案。如果无论如何
不能满足要求就输出无解。
首先可以发现,可以把编号为(a,a+K,a+2K...)的一批人分成一组(在模
N的意义下),这样共可以分成gcd(K,N)组,不同的组之间没有影响。于
是可以把每组分开来考虑。
对于(a,a+K,a+2K,...)这样一个序列来说,设B[1],B[2],B[3]...是需要
的杯子数,而x[1],x[2],x[3]...是侍者分别对(a,a+K),(a+K,a+2K),(a+
2K,a+3K)这些“相邻”的人的操作次数(不妨设拿上为正,拿下为负),
则有如下方程组:
x[1] + x[2] = B[2]
x[2] + x[3] = B[3]
...
x[n-1] + x[n] = B[n]
x[1] + x[n] = B[1]
这是一个系数矩阵很有规律的线性方程组,手算一下可以发现,当N(即
一个组的长度)为奇数时,方程组有唯一解。而且利用矩阵的特殊性可
以是O(n)的时间内算出来。当N为偶数时,方程组有无数解,会出现一个
自由变量,这样侍者的操作次数是一个类似下面形式的分段函数
F(x) = abs(x-a1) + abs(x-a2) + ... abs(x-an)
其中x是自由变量的取值。
于是就可以枚举x所在的区间,求出F(x)的最大值。
实际上,注意到题目中杯子数不大于1000的限制,可以直接枚举自由变量
的取值再每次用O(n)检验,也是与O(n^2)相同的复杂度。这种方法简便且
不易出错。


