题目链接:点击这里
题目大意: n n n 个人,分成了 m m m 组,每组每人每回合会造成 1 1 1 点伤害,每回合会让人数最多的组减少 k k k 人,不足 k k k 人就把组内所有人全部去除,问这 n n n 人共会造成多少伤害
题目分析:
对于每一组来说,
k
+
x
k+x
k+x 人和
x
x
x 人的结果对答案是一样的,不管是哪一组多了
k
k
k 最后都会在一回合减少
k
k
k 变成
x
x
x ,因此只需枚举完整的
k
k
k 的个数(在
[
⌊
n
k
⌋
−
m
,
⌊
n
k
⌋
]
[\ \lfloor \frac nk \rfloor -m , \lfloor \frac nk \rfloor\ ]
[ ⌊kn⌋−m,⌊kn⌋ ] 范围内枚举)而不需要将其分配到具体的某一组当中去,然后再将剩下的平均分,最后运用等差数列求和公式计算各部分贡献即可
解释一下
c
a
l
(
g
r
o
u
p
)
cal(group)
cal(group) 函数:分出了
g
r
o
u
p
group
group 个
k
k
k 时的贡献
在前
g
r
o
u
p
group
group 回合
k
k
k 组被消灭,在这
g
r
o
u
p
group
group 回合里造成的伤害为
[
n
+
(
n
−
k
(
g
r
o
u
p
−
1
)
)
]
∗
g
r
o
u
p
2
=
[
2
n
−
k
(
g
r
o
u
p
−
1
)
]
∗
g
r
o
u
p
2
\frac {[n+(n-k(group-1))]*group}2\ =\ \frac {[2n-k(group-1)]*group}2
2[n+(n−k(group−1))]∗group = 2[2n−k(group−1)]∗group ,
n
o
w
now
now 为
g
r
o
u
p
group
group 会合后剩余人数,
x
x
x 为
m
m
m 组中人数为
⌈
n
o
w
k
⌉
\lceil \frac {now}k \rceil
⌈know⌉ 的组数,
y
y
y 为
m
m
m 组中人数为
⌊
n
o
w
k
⌋
\lfloor \frac {now}k \rfloor
⌊know⌋ 的人数
其贡献分别为
n
o
w
−
[
n
o
w
−
(
t
m
p
+
1
)
(
x
−
1
)
]
2
=
[
2
n
o
w
−
(
t
m
p
+
1
)
(
x
−
1
)
]
∗
x
2
\frac {now-[now-(tmp+1)(x-1)]}2 \ =\ \frac {[2now-(tmp+1)(x-1)]*x}2
2now−[now−(tmp+1)(x−1)] = 2[2now−(tmp+1)(x−1)]∗x ,
(
t
m
p
+
t
m
p
∗
y
)
y
2
\frac {(tmp+tmp*y)y}2
2(tmp+tmp∗y)y ,其中
t
m
p
=
⌊
n
o
w
k
⌋
tmp = \lfloor \frac {now}k \rfloor
tmp=⌊know⌋
具体细节见代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
ll read()
{
ll res = 0,flag = 1;
char ch = getchar();
while(ch<'0' || ch>'9')
{
if(ch == '-') flag = -1;
ch = getchar();
}
while(ch>='0' && ch<='9')
{
res = (res<<3)+(res<<1)+(ch^48);//res*10+ch-'0';
ch = getchar();
}
return res*flag;
}
ll n,m,k;
ll cal(int group)
{
ll res = (2*n-(group-1)*k)*group/2;
ll now = n-group*k;
ll tmp = now/m;
ll x = now%m;ll y = m-x;
res += (2*now-(tmp+1)*(x-1))*x/2;
res += (tmp+tmp*y)*y/2;
return res;
}
int main()
{
n = read(),m = read(),k = read();
ll ans = 0;
for(ll i = max(0LL,n/k-m);i <= n/k;i++)//避免从负组数开始枚举所以加了个max
ans = max(ans,cal(i));
printf("%lld",ans);
}