题解 | #D 与数列#

D 与数列

https://ac.nowcoder.com/acm/problem/229428

内测一血。

考虑先满足中位数为 AA 的条件:

构造 a={A1,A1,,A1,A,A+1,,A+1,A+1}a=\{\color{red}A-1,A-1,\cdots,A-1\color{black},A,\color{blue}A+1,\cdots,A+1,A+1\color{black}\}

不难发现此时一定满足中位数为 AA

然后就是考虑如何让平均数为 BB 了,由于这题对于 aia_i 的值域限制放得很宽,可以考虑把这个影响均摊到剩余的所有数上,具体的做法是:

  • 分类讨论。
  • 若当前平均数 ave<Bave<B,证明需要调大,就将 Δ\Delta(差值)摊到后面的 {A+1}\{A+1\} 上。
  • 若当前平均数 ave>Bave>B,证明需要调小,就将 Δ\Delta(差值)摊到前面的 {A1}\{A-1\} 上。

具体的“摊”法是:

  • 构建一个 for 循环,首先将 Δ=sumn×B\Delta=sum-n\times B 计算出来,然后计算出 Δ\Delta 除以数的个数 numnum 下取整的值,这个值摊到每个 aia_i 上,剩下来的余数直接扔给首/末元素即可。
signed main(){
	int n = init(), A = init(), B = init();
    for (int i = 1; i <= n; ++i)
        if (i == (n + 1) / 2) a[i] = A;
        else if (i < (n + 1) / 2) a[i] = A - 1;
        else if (i > (n + 1) / 2) a[i] = A + 1;
    int sum = 0;
    for (int i = 1; i <= n; ++i) sum += a[i];
    sum -= n * B;
    if (sum == 0) { for (int i = 1; i <= n; ++i) print(a[i]), putchar(' '); } // 恰好可行直接输出
    else if (sum < 0) { // 小了就调大
        int now = -sum, num = n - (n + 1) / 2;
        for (int j = (n + 1) / 2 + 1; j <= n; ++j) a[j] += now / num; // 把“影响”摊给每个数
        a[n] += now % num;
        for (int i = 1; i <= n; ++i) print(a[i]), putchar(' ');
    }
    else { // 大了就调小
        int now = sum, num = (n + 1) / 2 - 1;
        for (int j = 1; j <= num; ++j) a[j] -= now / num; // 把“影响”摊给每个数
        a[1] -= now % num;
        for (int i = 1; i <= n; ++i) print(a[i]), putchar(' ');
    }
}
全部评论

相关推荐

昨天 22:34
已编辑
重庆邮电大学 Java
快手 客户端开发 (n+5)k*16 公积金12
点赞 评论 收藏
分享
CrazyBucket:我今天下午也做梦在招聘会上面试一家小厂,给自己气笑了
点赞 评论 收藏
分享
菜菜咪:1. 可以使用简历网站的模版,美观度会更好一点 2. 邮箱可以重新申请一个,或者用qq邮箱的别名,部分hr可能会不喜欢数字邮箱 3. 项目经历最好分点描述,类似的项目很多,可以参考一下别人怎么写的 4. 自我评价可加可不加,技术岗更看重技术。最后,加油,优秀士兵
点赞 评论 收藏
分享
2 1 评论
分享
牛客网
牛客企业服务