内存

2.1 Problem Statement
小 D 正在研究信息在内存中的存储。
小 D 共有 n 条信息,依次编号为 1, 2, · · · , n,第 i 条信息的大小为 ai。
小 D 可以将这些信息分为连续的 k 组,每组存入一个内存单元,每组需要的存
储空间为这组中所有信息大小之和。
小 D 可以使用压缩技术将每条信息的大小同时从 ai 变为 (ai + x) mod m,其中
x 为一个小 D 自己选定的整数。
小 D 想要知道,这 k 组信息需要的存储空间最大值最小可以是多少。
但是小 D 并不会,请你帮帮他。

2.2 Input Format
从标准输入读入数据。
第一行三个正整数 n, m, k 表示信息条数,压缩技术的参数以及内存单元个数。
第二行 n 个空格隔开的正整数 a1, a2, · · · , an,表示每条信息的大小。

2.3 Output Format
向标准输出输出答案。
输出一行一个整数表示这个最大值的最小值。
2.4 Sample 1

2.4.1 Input
5 5 2
0 4 2 1 3
2.4.2 Output
5
2.4.3 Explanation
取 x = 3,则 a= [3, 2, 0, 4, 1],分配方案为 {[3, 2, 0], [4, 1]},则需要的存储空间
最大值为 5。

2.5 Sample 2
见下发文件 memory/memory2.in 与 memory/memory2.ans。
2.6 Sample 3
见下发文件 memory/memory3.in 与 memory/memory3.ans。

2.7 Constraints
对于所有测试数据,1 ≤ k ≤ n ≤ 105,1 ≤ m ≤ 1000,0 ≤ ai < m。
• 子任务 1(30 分):n ≤ 20,m ≤ 50;
• 子任务 2(30 分):n ≤ 1000;
• 子任务 3(40 分):无特殊限制。
题解:
水题,但又很颠覆。。。
容易想到,枚举x,二分答案,时间复杂度O(nmlogn),会TLE
但同时我们又发现,实际上大量的x都是无用的。
所以我们可以随机处理,每次随机一个x,先判重和是否有贡献,这样能减少大量时间,同时提高正确率。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <ctime>
 
using namespace std;
 
const int maxn = 100000;
const int maxm = 1000; 
 
int n, m, k, p;
int a[maxn + 5], sum;
int l, r, L;
bool vis[maxm + 5];
 
inline int qmod(int x) { return (x >= m) ? x - m : x; }
 
inline int random(int x) { return (long long) rand()*rand() % x; }
 
inline bool check(int x) {
    int cnt, sum, now;
    cnt = sum = 0;
    for (int j = 1; j <= n; j++) {
        now = qmod(a[j] + p);
        if (now > x) return 0;
        if (sum + now > x) cnt++, sum = now;
        else sum += now;
    }
    if (sum > 0) cnt++;
    if (cnt <= k) return 1;
    return 0;
}
 
int main() {
    l = 1e9;
    scanf("%d %d %d", &n, &m, &k);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]), r += a[i], l = min(l, a[i]);
    L = l;
    srand((unsigned)(time(0)));
    for (int ti = 0; ti < min(m, 1000); ti++) {
        p = random(m);
        if (vis[p]) { ti--; continue; } vis[p] = 1;
        bool can = 1;
        if (!check(r - 1)) continue;
        l = L;
        while (l < r) {
            int mid = (l + r) >> 1;
            if (check(mid)) r = mid;
            else l = mid + 1;
        }
    }
    //printf("%d\n", check(5));
    printf("%d\n", r);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值