2017多校八 1008题 hdu 6140 Hybrid Crystals 推理

34 篇文章 0 订阅
8 篇文章 0 订阅

题目链接

题意

给定 n (1n103) 个非负整数,有些系数为 1 ,有些为 1,有些可为 1 可为 1,要求选取其中的一个子集,使得和为 k (|k|106).
此外,这 n 个数还满足一些特殊条件:
1. a1=1,其系数可正可负
2.

aij=1i1aj[bj=N]+j=1i1aj[bi=Lbj=L]+j=1i1aj[bi=Dbj=D](2in).

玄学?非也

比赛时破罐子破摔直接判断 k 在不在左右两个端点范围内,竟然就过了,然而这是为什么呢?

结论

这道题中的数能组成的数构成了一个连续区间.

证明

关注一下上面的两个条件,由条件 1 a[1] 结束后可以连续(即区间内每一个元素均可)取到的范围为 [1,1] .
不妨设处理到第 i 个元素结束时可以连续取到的范围为 [Lo,Hi] , 显然有

Lo=(bj=Njiaj+bj=Daj),Hi=bj=Njiaj+bj=Laj.

1. 假设第 i+1 个元素的属性为 L ,
则根据条件 2, aiij=1aj[bj=N]+ij=1aj[bj=L]=Hi ,即 aiHi
[0,Hi]+ai=[ai,Hi+ai] ,有 aiHi ,故 [Hi,Hi+ai][ai,Hi+ai]
原范围 新范围即为 [Lo,Hi][Hi,Hi+ai]=[Lo,Hi+ai] ,且连续
2. 假设第 i+1 个元素的属性为 D ,
与上同理
3. 假设第 i+1个元素的属性为 N ,
则根据条件 2, aiij=1aj[bj=N]Hi,aiij=1aj[bj=N]Lo , 亦与上同理.
由数学归纳法得: 这道题中的数能组成的数构成了一个连续区间.

所以上面的玄学做法(大雾)就是有理有据的了

Code

#include <bits/stdc++.h>
#define maxn 1010
#define maxl 2000010
typedef long long LL;
const LL mod = 1e9 + 7;
inline int max(int a, int b) { return a > b ? a : b; }
inline int min(int a, int b) { return a < b ? a : b; }
int a[maxn], id[maxn]; char c;
bool dp[maxl];
void work() {
    memset(dp, 0, sizeof(dp));
    int n, k;
    scanf("%d%d", &n, &k);
    for (int i = 0; i < n; ++i) scanf("%d", &a[i]);
    scanf("\n%c", &c);
    int netu = a[0], nega = 0, posi = 0;
    for (int i = 1; i < n; ++i) {
        scanf(" %c", &c);
        if (c == 'L') posi += a[i];
        else if (c == 'D') nega -= a[i];
        else netu += a[i];
    }
    int le = nega - netu, ri = posi + netu;
    if (k < le || k > ri) {
        printf("no\n");
        return;
    }
    printf("yes\n");
}
int main() {
    int T;
    scanf("%d", &T);
    while (T--) work();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值