链接:https://www.nowcoder.com/acm/contest/94/K
来源:牛客网
分析:n的最大值能达到35,有2^35种状态,不能直接枚举所有的状态。
但可以把n分成两个部分,这样每个部分的状态枚举就能在规定时间内达到。
设i为第一个部分的状态,j为第二个部分的状态。
则有(ai+aj)/(bi+bj)=x/y,进一步化为 ai*y-bi*x=bj*x-aj*y
就可以在将每个第一部分的状态,通过二分找到第二部分中能与之匹配的状态
代码如下:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; const int MAXN=40; typedef long long LL; int a[MAXN]; int b[MAXN]; int t,x,y,n,n1,n2,nowa,nowb; LL ans; int poi1[1000100],poi2[1000100]; int main() { ios::sync_with_stdio(false); cin>>t; while(t--) { ans=0; int cnt1=1; int cnt2=1; cin>>n>>x>>y; for(int i=1;i<=n;i++) cin>>a[i]>>b[i]; n1=n/2; for(int i=0;i<(1<<n1);i++) { nowa=0; nowb=0; for(int j=1;j<=n1;j++) { if(i&(1<<(j-1))) { nowa+=a[j]; nowb+=b[j]; } } poi1[cnt1]=nowa*y-nowb*x; cnt1++; } n2=n-n1; for(int i=0;i<(1<<n2);i++) { nowa=0; nowb=0; for(int j=1;j<=n2;j++) { int k=j+n1; if(i&(1<<(j-1))) { nowa+=a[k]; nowb+=b[k]; } } // cout<<cnt2<<" "<<nowa<<" "<<y<<" "<<nowb<<" "<<x<<endl; poi2[cnt2]=nowa*y-nowb*x; cnt2++; } sort(poi2+1,poi2+cnt2); for(int i=1;i<cnt1;i++) { int need=-poi1[i]; ans+=upper_bound(poi2+1,poi2+cnt2,need)-lower_bound(poi2+1,poi2+cnt2,need); } cout<<ans-1<<endl; } return 0; }