Codeforces 920D Tanks
题目链接
题意
有 \(n\) 个容积无限的水缸,初始时水量为\(a_1,a_2,...,a_n\),有一把容积为\(k\)的勺子,可以从一个水缸中舀水倒入另一个水缸中。问能否给出操作序列,使得最终某一个水缸中水的容量为\(V\).
思路
参考 - 粉兔.
结论
首先,如果\(\sum_{i=1}^{n}a_i\lt V\),显然不可行。
否则,一旦\(\exists p_1,p_2,...,p_t,s.t.(\sum_{i=1}^{t}a_{p_i})\%k==V\%k\),则我们说,这件事是可行的。
为什么呢?因为一旦可以取到同余的值,那么无论总量是多余还是不足都可以用勺子解决:多了,就往外舀;少了,就从其他缸(\(i.e.\) 第\(j\)个\((j!=p_i(i=1,2,...,t)\)))中补进来。
至于操作的具体细节,暂放一下。
dp
那么该怎么判断是否有上面的条件成立呢?
用 \(dp[i][j]\) 表示前 \(i\) 个缸能否取到模数为 \(j\) 的值,特别的,
\]
则 \(dp[n][V\%k]\) 即表示前 \(n\) 个缸能否取到模数为 \(k\) 的值。
构造
现在有了这个结论和中间记录的 \(dp\) 值,该怎么推出步骤呢?
注意到,上面的记录过程提供给了我们 \(p_1,p_2,...,p_t\),即必须全部取的缸;而其余的缸,不妨记为 \(q_1,q_2,...,q_s\)。
则可行操作如下:
- 将 \(p1,...,p_{t-1}\) 缸中的水全部舀入 \(p_t\) 中;
 - 将 \(q1,...,q_{s-1}\) 缸中的水全部舀入 \(q_s\) 中;
 - 在 \(p_t\) 与 \(q_s\) 之间进行多退少补。
 
注意几种 特殊情况,比如 \(t=n\) 和 \(s=n\) 的情况:
\(t=n\) 即所有的缸都需要,最后总量肯定只会超出,不会不够,并且超出的部分必然是 \(k\) 的整倍数。
此时,将所有缸中的水都舀到某一个缸中,再将超出的部分舀到另一个缸中;
(这种情况可以与一般情况合在一起统一处理)。
\(s=n\) 即所有的缸都不需要,这是什么回事呢?当 \(k|V\) 时就会发生这种情况,即所需要的容积恰好可以用若干勺舀出。
此时,将所有缸中的水都舀到某一个缸中,再将需要的部分舀到另一个缸中。
// 很佩服粉兔啦%%%
Code
#include <bits/stdc++.h>
#define maxn 5010
using namespace std;
typedef long long LL;
int a[maxn], b[maxn], dp[maxn][maxn];
bool flag[maxn];
int main() {
    int n, k, v, sum = 0;
    scanf("%d%d%d", &n, &k, &v);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        sum += (b[i] = a[i]), a[i] %= k;
    }
    if (sum < v) { puts("NO"); return 0; }
    dp[0][0] = 1;
    for (int i = 1; i <= n; ++i) {
        for (int j = 0; j < k; ++j) {
            if (dp[i-1][j]) {
                dp[i][j] = 1;
                if (!dp[i][(j+a[i])%k]) dp[i][(j+a[i])%k] = 2;
            }
        }
    }
    int tar = v % k;
    if (!dp[n][tar]) { puts("NO"); return 0; }
    puts("YES");
    int ans = 0, fnl1 = -1, fnl2 = -1;
    for (int i = n; i >= 1; --i) {
        if (dp[i][tar]==2) {
            flag[i] = true, (tar += k-a[i]) %= k, ans += b[i];
            if (fnl1==-1) fnl1 = i;
        }
        else if (fnl2 == -1) fnl2 = i;
    }
    if (fnl1==-1) {
        for (int i = 1; i < n; ++i) if (b[i]) {
            printf("%d %d %d\n", (b[i] + k-1)/k, i, n);
        }
        if (v/k) printf("%d %d %d\n", v/k, n, 1);
        return 0;
    }
    assert((v-ans) % k == 0);
    int rem = v - ans;
    int S1 = b[fnl1], S2 = b[fnl2];
    for (int i = 1; i <= n; ++i) {
        if (i == fnl1 || i == fnl2 || !b[i]) continue;
        if (!flag[i]) printf("%d %d %d\n", (b[i]+k-1)/k, i, fnl2), S2 += b[i];
        else printf("%d %d %d\n", (b[i]+k-1)/k, i, fnl1), S1 += b[i];
    }
    assert((v-S1) % k == 0);
    int cnt = (v-S1) / k;
    if (cnt>0) printf("%d %d %d\n", cnt, fnl2, fnl1);
    else if (cnt<0) printf("%d %d %d\n", -cnt, fnl1, 1);
    return 0;
}
												
											Codeforces 920D Tanks的更多相关文章
- Codeforces Educational Round 37
		
Solved CodeForces 920A Water The Garden Solved CodeForces 920B Tea Queue Solved CodeForces ...
 - Codeforces Round #115 B. Plane of Tanks: Pro 水题
		
B. Plane of Tanks: Pro Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/17 ...
 - Codeforces 877 C. Slava and tanks
		
http://codeforces.com/problemset/problem/877/C C. Slava and tanks time limit per test 2 seconds me ...
 - codeforces 414D Mashmokh and Water Tanks
		
codeforces 414D Mashmokh and Water Tanks 题意 题解 \(a_i\):第 \(i\) 层的结点个数. \(b_i\):第 \(i\) 层初始有水的结点个数. 如 ...
 - 【codeforces 175D】 Plane of Tanks: Duel
		
http://codeforces.com/problemset/problem/175/D (题目链接) 题意 A,B两人玩坦克大战,坦克有生命值,射击间隔,伤害范围,未命中的概率.问A赢的概率是多 ...
 - Codeforces 877C Slava and tanks(思维)
		
题目链接:http://codeforces.com/problemset 题目大意:有n个格子,某些格子里可能有一个或多个坦克,但不知道具体位置,每个坦克被轰炸一次就会移动到相邻的格子里(第1个格子 ...
 - 【Codeforces Round #442 (Div. 2) C】Slava and tanks
		
[链接] 我是链接,点我呀:) [题意] 有n个位置,每个位置都可能有不定数量的tank; 你每次可以选择一个位置投掷炸弹. 并且,这个位置上的所有tank都会受到你的攻击. 并且失去一点体力. 然后 ...
 - Codeforces Round #339 (Div. 2) B. Gena's Code 水题
		
B. Gena's Code 题目连接: http://www.codeforces.com/contest/614/problem/B Description It's the year 4527 ...
 - Educational Codeforces Round 37
		
Educational Codeforces Round 37 这场有点炸,题目比较水,但只做了3题QAQ.还是实力不够啊! 写下题解算了--(写的比较粗糙,细节或者bug可以私聊2333) A. W ...
 
随机推荐
- ECMAScript 6入门扩展笔记
			
字符串扩展 Unicode相关补充 引入"\u{xx}"来表示码点,之前只能表示\u0000-\uffff引入String.fromCodePoint()能正确读取大于uFFFF的 ...
 - 怎么把myeclipse项目导入IDEA中
			
先把myeclipse下的项目拷贝到IDEA的部署目录中,把一些不用的配置文件删除,只留下一个干净的项目 打开IDEA,点击import Project,引入一个项目,选择IDEA部署目录下刚拷贝过去 ...
 - 了解Windows Server以及Hyper-V许可模式
			
在2015年11月,微软宣布对Windows Server 2016以及Hyper-V的许可模式进行重大变更,并于2016年第三季度正式生效,Windows Server 2016标准版及数据中心版的 ...
 - Quorum机制与NRW算法总结
			
Quorum机制与NRW算法总结 1.Quorum机制 Quorum,原指为了处理事务.拥有做出决定的权力而必须出席的众议员或参议员的数量(一般指半数以上). 2.NRW算法 NRW算法是基于Quor ...
 - 实时视频h5
			
http://www.cnblogs.com/dotfun/p/4286878.html
 - 聊聊、Java 命令 第一篇
			
网上很多讲 Javac 和 Java 命令的,我觉得还是要自己写一写,做一个自己的总结,也方便以后查询. 开始之前先看看 help 命令,基本上任何一个软件都会提供这个命令. 没有什么比 -help ...
 - 实战项目——获取图片中的GPS位置信息和拍摄时间
			
今天突然看到有人写过获取图片中位置信息的程序.我觉得很有趣,也就自己实践了一下,研究了一下 话不多说,先上代码 #!/usr/bin/env python3 # -*- coding: utf-8 - ...
 - k8s与CICD--借助scp插件实现非容器项目的部署
			
一直没有时间完成drone系列文章.drone-wechat插件实现了一半,由于企业微信token申请比较麻烦,所以也没有进展.今天抽出时间,研究了一下scp插件,主要目的是实现非容器项目的部署.其实 ...
 - TOJ 4689: Sawtooth
			
4689: Sawtooth Time Limit(Common/Java):1000MS/3000MS Memory Limit:65536KByteTotal Submit: 26 ...
 - 201621123034 《Java程序设计》第1周学习总结
			
1. 本周学习总结 知道了java的用途有安卓手机应用,企业服务器后端,java web.学到了新概念:类.HelloWorld.java 中 HelloWorld 是主文件名,区分 .java和 . ...