[题解]GYM 100506C Cutting Banknotes

题意

给定一个数 x,以及 n 种不同面值的钞票 ai。(其中 x 可能是一个小数,但是 ai 一定是整数)

你可以将 ai 除以 2,得到新的面值。

如果你能通过这种方式,能够凑出 x,输出 yes,否则输出 no

思路

首先,有一个显然的结论:如果 x 不是形如 a.00,a.25,a.50,a.75 的数,那么一定无解。

剩下的我的第一反应是一个完全背包。

首先将 ai 一直除以 2,直到不能被 2 整除,再除以 8

这样一定能保证新的 ai 能够取若干个得到原来的 ai,使得结果不变。

但是,这样的处理会产生小数,所以用了一个 unordered_map 来搞。

显然,这样时间复杂度为错。

那么考虑将原本的 x 乘上 8,这样能保证结果不变,且时间复杂度少 Θ(logn)

但是,有一组 hack

这组数据明显是输出 yes,因为 5+11=1616 能够通过一直除以 2 得到 1。但是,按照这种思路会输出 no

那么,我们将值域开大一点,改为 x×64 就行。

Code

#include <bits/stdc++.h>  
#define re register  
  
using namespace std;  
  
const int N = 1010,M = 1e6 + 10;  
const double eps = 1e-6;  
int T,n,m;  
int arr[N];  
bool dp[M];  
double x;  
  
inline int read(){  
    int r = 0,w = 1;  
    char c = getchar();  
    while (c < '0' || c > '9'){  
        if (c == '-') w = -1;  
        c = getchar();  
    }  
    while (c >= '0' && c <= '9'){  
        r = (r << 3) + (r << 1) + (c ^ 48);  
        c = getchar();  
    }  
    return r * w;  
}  
  
inline bool cmp(double a,double b){  
    return (fabs(a - b) <= eps);  
}  
  
inline bool check(double x){  
    int A = x;  
    double B = x - A;  
    return (cmp(B,0.0) || cmp(B,0.25) || cmp(B,0.5) || cmp(B,0.75));  
}  
  
int main(){  
    T = read();  
    while (T--){  
        memset(dp,false,sizeof(dp));  
        dp[0] = true;  
        scanf("%lf",&x);  
        n = read();  
        m = x * 64;  
        if (!check(x)){//特判无解   
            puts("no");  
            for (re int i = 1;i <= n;i++) arr[i] = read();  
            continue;  
        }  
        for (re int i = 1;i <= n;i++){  
            arr[i] = read();  
            while (!(arr[i] & 1)) arr[i] >>= 1;//处理新的值   
        }  
        sort(arr + 1,arr + n + 1);  
        int nn = unique(arr + 1,arr + n + 1) - arr - 1;//离散化,经试验在一般情况下能将 n 个元素降低为 n / 2 个元素   
        for (re int i = 1;i <= nn;i++){//完全背包   
            for (re int j = arr[i];j <= m;j++) dp[j] |= dp[j - arr[i]];  
            if (dp[m]) break;  
        }  
        if (dp[m]) puts("yes");  
        else puts("no");  
    }  
    return 0;  
}  

作者:WaterSun

出处:https://www.cnblogs.com/WaterSun/p/18268785

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   WBIKPS  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示