博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
uestc1633
阅读量:6980 次
发布时间:2019-06-27

本文共 1276 字,大约阅读时间需要 4 分钟。

题意

给你一个大小为 \(n\) 的集合 \(S\) ,集合里有 \(n\) 个互不相同正整数,有 \(q\) 个询问,每次询问是否能选择 \(S\) 中的一些数字 ( 同一个数字可以选择多次,也可以任何数字都不选),使它们相加的和为 \(m\)

分析

这种题型 竟然 可以套用最短路的模型。

如果 \(k\) 在集合中,那么如果 \(a\) 是合法的和的方案,那么 \(a + k\) 一定是合法的。

那么我们只要求出 \(\% k\) 后得到 \([0, k - 1]\) 这些数的最小的和( \(d\) 数组)。那么判断是否可以组成 \(m\) ,只需要 \(m >= d[m \% k]\)

主要就是维护一个小的先出的优先队列 ,所以先出来的值 ( 假设是 \(x\) ) \(\% k\) 的相同的余数中一定是最小的,这个时候就要标记 \(vis[x \% k] = 1\) ,所有后面出来的值 \(y\) ,如果 \(vis[y \% k]\) 已经标记过 ( 假设就是前面的 \(x\) 标记的 ) ,可以直接跳过,因为 \(x \% k == y \% k\) ,且 \(x < y\) ,前面 \(x\) 出队列后已经更新了其它的可能出现的余数,在拿 \(y\) 去更新就没必要了。

code

#include
using namespace std;const int MAXN = 2e3 + 10;const int INF = 1e9 + 7;int n, a[MAXN];int d[50005];int vis[50005];void dij(int w) { priority_queue
, greater
> q; fill(d, d + w, INF); q.push(0); d[0] = 0; while(!q.empty()) { int now = q.top(); q.pop(); if(vis[now % w]) continue; vis[now % w] = 1; for(int i = 0; i < n; i++) { int dist = now + a[i]; if(dist < d[dist % w]) { d[dist % w] = dist; q.push(dist); } } }}int main() { scanf("%d", &n); int w = INF; for(int i = 0; i < n; i++) { scanf("%d", &a[i]); w = min(w, a[i]); } dij(w); int q; scanf("%d", &q); while(q--) { int m; scanf("%d", &m); puts(m >= d[m % w] ? "YES" : "NO"); } return 0;}

转载于:https://www.cnblogs.com/ftae/p/7291774.html

你可能感兴趣的文章
常用的JQuery数字类型验证正则表达式
查看>>
JVM堆 栈 方法区详解
查看>>
PL/SQL程序设计 第七章 包的创建和应用
查看>>
html标签的显示模式(块级标签,行内标签,行内块标签)(转)
查看>>
Python 爬虫练手项目—酒店信息爬取
查看>>
java实现用户登录注册功能(用集合框架来实现)
查看>>
找子串替换(kmp)poj1572
查看>>
sql server 的一些记录
查看>>
mongodb启动
查看>>
Oracle 聚合函数(Aggregate Functions)说明
查看>>
关闭所有cloudfoundry应用进程
查看>>
迈斯!啊呸~数学
查看>>
一则利用内核漏洞获取root权限的案例【转】
查看>>
was unable to refresh its cache! status = Cannot execute request on any known server
查看>>
QButtonGroup 的使用
查看>>
1968年12月9日,恩格尔巴特公开演示了世界上第一个鼠标盒子
查看>>
php中序列化与反序列化
查看>>
C语言双链表遍历,插入,删除
查看>>
关于git bush 中不能复制黏贴的问题
查看>>
java中的移位运算符
查看>>