时间限制:1.0s
空间限制:256MB
题目描述
Jimmy到Symbol的手表店买手表,Jimmy 只带了
n
n
n种钱币,第
i
i
i种钱币的面额为
k
k
ki元,张数为
a
a
ai张。Symbol 的店里一共有
m
m
m块手表,第i块手表的价格为
t
t
ti元。
Symbol的手表店不能找零,所以Jimmy只能在凑出恰好的钱数时才能购买一块手表。现在对于店里的每块手表, Jimmy想知道他能不能凑出恰好的钱数进行购买。
输入格式
第一行两个空格分隔的整数
n
n
n和
m
m
m表示钱币数与手表数。
接下来n行每行两个空格分隔的整数
k
k
ki和
a
a
ai表示钱币的面额和张数。
第
n
+
2
n+2
n+2行,共m个用空格分隔的整数
t
t
t
i
i
i,表示每块手表的价格。
输出格式
一共 m m m行,对于第 i i i行,如果能凑出恰好的钱数购买第 i i i块手表则输出"Yes" (不含引号,下同),否则输出"No",注意只有首字母大写。
样例1输入
3 5
1 2
5 1
6 3
3 19 21 1 7
样例1输出
No
Yes
No
Yes
Yes
样例1解释
第二块手表
19
=
6
∗
3
+
1
=
6
∗
2
+
5
+
1
∗
2
19=6*3+1= 6*2+5+1*2
19=6∗3+1=6∗2+5+1∗2,可以恰好凑出。
第四块手表
1
=
1
∗
1
1= 1*1
1=1∗1,可以恰好凑出。
第五块手表
7
=
5
+
2
∗
1
=
6
∗
1
+
1
7=5+2*1=6*1+ 1
7=5+2∗1=6∗1+1,可以恰好凑出。
数据范围与提示
对于
50
50
50%的数据,
n
≤
10
n≤10
n≤10,
m
≤
60
m≤60
m≤60,
a
a
ai
≤
20
≤20
≤20,
k
k
ki
≤
5000
≤5000
≤5000,
t
t
t i
≤
250
≤250
≤250。
对于
100
100
100%的数据,
1
≤
n
≤
200
,
1
≤
m
≤
105
,
1
≤
1≤n≤200, 1≤m≤105, 1≤
1≤n≤200,1≤m≤105,1≤
a
a
ai
≤
1000
≤1000
≤1000,
1
≤
1≤
1≤
k
k
ki
≤
500000
≤500000
≤500000,
0
≤
0≤
0≤
t
t
ti
<
500000
< 500000
<500000
本人在考试的时候脑子抽筋了,导致最后dp超时,赛后发现可以通过二进制状态压缩dp卡数据
代码:
#include<bits/stdc++.h>
#define maxn 205
#define ll long long
using namespace std;
int n,m,x,cnt;
ll k[maxn],a[maxn],v[maxn*20],dp[500005];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>k[i]>>a[i];
for(int j=1;j<=a[i];j<<=1){
v[++cnt]=j*k[i];
a[i]-=j;
}
if(a[i])v[++cnt]=a[i]*k[i];
}
dp[0]=0;
for(int i=1;i<=cnt;i++){
for(int j=500000;j>=v[i];j--){
dp[j]=max(dp[j],dp[j-v[i]]+v[i]);
}
}
while(m--){
cin>>x;
if(dp[x]==x)cout<<"Yes
";
else cout<<"No
";
}
return 0;
}