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 }
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 }