吃東西
阿新 • • 發佈:2017-10-11
first break auto scan 暴力 其中 cst lin bar
吃東西
Time Limit:2000ms Memory Limit:1024MB
題目描述
一個神秘的村莊裏有4家美食店。這四家店分別有A,B,C,D種不同的美食。LYK想在每一家店都吃其中一種美食。每種美食需要吃的時間可能是不一樣的。
現在給定第1家店A種不同的美食所需要吃的時間a1,a2,…,aA。
給定第2家店B種不同的美食所需要吃的時間b1,b2,…,bB。
以及c和d。
LYK擁有n個時間,問它有幾種吃的方案。
輸入格式
第一行5個數分別表示n,A,B,C,D。
第二行A個數分別表示ai。
第三行B個數分別表示bi。
第四行C個數分別表示ci。
第五行D個數分別表示di。
輸出格式
一個數表示答案。
輸入樣例
11 3 1 1 1
4 5 6
3
2
1
輸出樣例
2
對於30%的數據A,B,C,D<=50
對於另外30%的數據n<=1000。
對於100%的數據1<=n<=100000000,1<=A,B,C,D<=5000,0<=ai,bi,ci,di<=100000000。
題解
暴力A*B求出A和B組合的所有方案。
暴力C*D求出C和D組合的所有方案。
再把AB和CD的方案組合。
n太大,不能用sort排序。
因為空間足夠大,可以按數值存一個數組,再O(n)從小到大放進去。
因為具有單調性,可以O(n)算出方案數。
代碼
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<iostream> #define LL long long using namespace std; const int N=100000005,M=5005; int A,B,C,D,n,maxn,cntab,cntcd,now; int a[M],b[M],c[M],d[M]; int f[N],ab[M*M],cd[M*M]; LL ans; int main(){ scanf("%d%d%d%d%d",&n,&A,&B,&C,&D); for(int i=1;i<=A;i++)scanf("%d",&a[i]); for(int i=1;i<=B;i++)scanf("%d",&b[i]); for(int i=1;i<=A;i++) for(int j=1;j<=B;j++) if(a[i]+b[j]<=n){ f[a[i]+b[j]]++; maxn=max(maxn,a[i]+b[j]); } for(int i=0;i<=maxn;i++) while(f[i]){ f[i]--; ab[++cntab]=i; } for(int i=1;i<=C;i++)scanf("%d",&c[i]); for(int i=1;i<=D;i++)scanf("%d",&d[i]); maxn=0; for(int i=1;i<=C;i++) for(int j=1;j<=D;j++) if(c[i]+d[j]<=n){ f[c[i]+d[j]]++; maxn=max(maxn,c[i]+d[j]); } for(int i=0;i<=maxn;i++) while(f[i]){ f[i]--; cd[++cntcd]=i; } for(int i=cntcd;i>=1;i--) if(ab[1]+cd[i]<=n){ now=i; break; } for(int i=1;i<=cntab;i++){ ans+=now; while(now&&ab[i+1]+cd[now]>n)now--; } printf("%lld\n",ans); return 0; }
吃東西