1. 程式人生 > >小馬哥的超級鹽水

小馬哥的超級鹽水

HR 分享 b+ nbsp com string close clas 多少

來呀

題意:給n杯鹽水,每一杯水有a單位鹽,b單位水。給你一個x和y,問有多少種方法能配成x比y的鹽水。

因為n只有35,沒法枚舉全部情況,如果n只有一般大,那麽我們可以枚舉所有情況。

我們可以把n分為兩部分,枚舉一部分的所有情況,然後找是否能和另一部分構成解。

對於(a1,b1)和(a2,b2)這兩個集合。

易得(a1+a2)/(b1+b2)=x/y。

化簡得到(y*a1-x*b1)=(x*b2-y*a2)。所以枚舉前面的然後找後面的就行了。

AC代碼:

技術分享圖片
#include <iostream>
#include <string.h>
#include <iostream>
#include 
<algorithm> using namespace std; typedef long long ll; struct node{ ll ai,bi; }a[105]; ll b[1<<19]; int main() { int t;cin>>t; while(t--) { ll n; ll x,y;cin>>n>>x>>y; for(int i=0;i<n;i++) { cin>>a[i].ai>>a[i].bi; }
int p=0; ll n1=n/2; ll n2=n-n1; ll m1=(1<<n1); ll m2=(1<<n2); for(int i=0;i<(m2);i++) { ll sum=0; for(int j=0;j<n2;j++) { if((i>>j)&1) { sum+=a[j+n1].bi*x-a[j+n1].ai*y; } } b[p
++]=sum; //cout<<ans-1<<endl; } sort(b,b+p); ll ans=0; for(int i=0;i<m1;i++) { ll sum=0; for(int j=0;j<n1;j++) { if((i>>j)&1) { sum+=a[j].ai*y-a[j].bi*x; } } ans+=upper_bound(b,b+p,sum)-lower_bound(b,b+p,sum); } cout<<ans-1<<endl; } return 0; }
View Code

小馬哥的超級鹽水