小馬哥的超級鹽水 (牛客網景馳科技杯)
阿新 • • 發佈:2019-01-29
連結:https://www.nowcoder.com/acm/contest/94/K
來源:牛客網
題意:給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)。所以列舉前面的然後找後面的就行了。
#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; }