Codeforces#589 (DIv3)

A题:(数字凑配问题)   

Codeforces1256A

你有a个价值为n的硬币和b个价值为1的硬币,然后给你一个价值S,问你能不能用x个价值为n的硬币和y个价值为1的硬币(0<=x<=a),(0<=y<=b)凑出这个价值S

(a,b,n,S)都是在1到1e9范围之类的

一般想法???????   先列出扩展欧几里得定义,然后搞搞?  然而并不行?

另外一个为1?这个有什么好变动的东东?  

我们先用价值为n的来凑,凑到不能凑了之后,再用1来凑,这样如果都不行的话那么肯定就是不行的????

这个正确性是显然的,因为价值为n的比价值为1的更有用,这样的话我们使用的1是最少的,只要这样不超过的话,那么就不可能超过了。

首先我们知道1是很宝贵的,我们只有当n用完了或者n无法用的时候才开始考虑用1???????

这样是最好的。

下面是代码:

 1 #include <cmath>
 2 #include <bitset>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <cstring>
 6 typedef long long ll;
 7 using namespace std;
 8 int q;
 9 ll a,b,n,s;
10 int main(){
11     scanf("%d",&q);
12     while(q--){
13         scanf("%lld%lld%lld%lld",&a,&b,&n,&s);
14         ll t=s-min(s/n,a)*n;
15         if(t<=b) printf("YES\n");
16         else printf("NO\n");
17     }
18     return 0;
19 }
View Code

Codeforces1244C

让你解一个方程x*w+y*d=p;  x+y+z=n;(其中x,y,z>=0)

由于第二个方程基本没什么用,那个z不会在前面的x*w+y*d=p中有什么作用?   这样的话我们就可以忽略掉z的作用。

这样的话我们就可以转化成x+y<=n,然后x*w+y*d=p(这样转移过来?)

这样又变成了凑数字的模型???????????    又变成欧几里得的东东(但是不需要用扩展欧几里得)

这个的做法是你首先确定好最先用的一个(一般是最大的那个),先来凑配,因为大的那个能很好的等效掉小的那个,而且大的那个可以用更少的次数,这样的话选择余地更大,这样的话对可行性问题这种更好?

所以我们考虑用大的那个  ,然后d个w很显然能等效掉w个d,这样的话我们就可以确定我们的d的数量在0到w-1以内,这样的话我们如果多了的话就可以把它等效掉。

下面是题解:

 1 /*
 2     x*w+y*d=p;
 3     x+y+z=n;
 4     其中x,y,z>=0
 5 */
 6 #include <cmath>
 7 #include <algorithm>
 8 #include <iostream>
 9 #include <cstdio>
10 #include <bitset>
11 #include <cstring>
12 typedef long long ll;
13 using namespace std;
14 ll n,p,d,w;
15 int flag=0;
16 int main(){
17     scanf("%lld%lld%lld%lld",&n,&p,&w,&d);
18     for(ll i=0;i<=w;i++){
19         ll t=p-i*d;
20         if(t<0) continue;  if(t%w!=0) continue;
21         ll x=i,y=t/w;
22         if(x+y>n) continue;
23         printf("%lld %lld %lld\n",y,x,n-x-y);
24         flag=1;
25         break;
26     }
27     if(flag==0) printf("-1\n");
28     return 0;
29 }
View Code

猜你喜欢

转载自www.cnblogs.com/pandaking/p/11800884.html
今日推荐