官方解题报告:http://bestcoder.hdu.edu.cn/blog/2015-multi-university-training-contest-6-solutions-by-zju/
表示很难看。。。。orz
1003题 链接:http://acm.hdu.edu.cn/showproblem.php?pid=5355
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1138 Accepted Submission(s): 152
Special Judge
4 1 2 5 3 5 2 9 3
NO YES 1 5 2 1 4 2 2 3 NO YES 3 1 5 9 3 2 6 7 3 3 4 8
题意:n块蛋糕(大小1--n)分给m个人,要求每个人得到蛋糕大小总和相等
#include <iostream> #include <stdio.h> #include <string.h> #include <stack> #include <queue> #include <map> #include <set> #include <vector> #include <math.h> #include <bitset> #include <algorithm> #include <climits> using namespace std; #define ls 2*i #define rs 2*i+1 #define UP(i,x,y) for(i=x;i<=y;i++) #define DOWN(i,x,y) for(i=x;i>=y;i--) #define MEM(a,x) memset(a,x,sizeof(a)) #define W(a) while(a) #define gcd(a,b) __gcd(a,b) #define LL long long #define N 100005 #define INF 0x3f3f3f3f #define EXP 1e-8 #define rank rank1 const int mod = 1000000007; int t,n,m; int a[N]; int ans[15][N],tem[N],path[N],len[N]; LL sum; int main() { int i,j,k; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); sum = (n+1)*n/2; if(sum%m) { printf("NO\n"); continue; } sum/=m; MEM(tem,0); MEM(len,0); for(i = n;i>=1;i--) { for(j = 0;j<m;j++) { if(tem[j]+i<=sum) { tem[j]+=i; path[i]=j; break; } } } for(i = 0;i<m;i++) { if(tem[i]!=sum) break; } if(i!=m) { printf("NO\n"); continue; } for(i = 1;i<=n;i++) { k = path[i]; ans[k][len[k]++] = i; } printf("YES\n"); for(i = 0;i<m;i++) { printf("%d %d",len[i],ans[i][0]); for(j = 1;j<len[i];j++) { printf(" %d",ans[i][j]); } printf("\n"); } } return 0; }
1006题 链接:http://acm.hdu.edu.cn/showproblem.php?pid=5358
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 757 Accepted Submission(s): 230
1 2 1 1
12
思路:利用S(i,j)单调性, log2(S(i,j))+1= k =2^(k-1)<= S(i,j)<2^k
考虑枚举log(sum(i,j)+1的值,记为k,然后统计(i+j)的和即可。
对于每一个k,找到所有满足2^(k-1)<=sum(i,j)<=2^k-1的(i+j),
k<=2*log2(10^5)<34
转载请注明出处:寻找&星空の孩子
#include<stdio.h> #include<math.h> #include<algorithm> #define LL long long using namespace std; LL num[100005]; LL sum[100005]; int main() { int T; scanf("%d",&T); while(T--) { LL n; scanf("%lld",&n); num[0]=sum[0]=0; for(int i=1; i<=n; i++) { scanf("%lld",&num[i]); sum[i]=sum[i-1]+num[i]; } LL ans=0; for(LL k=1; k<=34; k++) { LL l=1,r=0;//注意r的初始值在l的左边;因为存在1个值的情况! LL KL=1LL<<(k-1); if(k==1) KL--; LL KR=1LL<<(k); for(LL i=1; i<=n; i++) { l=max(i,l);//区间左边界 while(l<=n&&sum[l]-sum[i-1]<KL) l++;//确定左边界 r=max(l-1,r);//区间右边界,注意r在l前的时候从l-1开始 while(r+1<=n&&sum[r+1]-sum[i-1]>=KL&&sum[r+1]-sum[i-1]<KR) r++;//确定区间右边界 if(r<l) continue; ans+=k*((i+l)+(i+r))*(r-l+1)/2; } } printf("%lld\n",ans); } return 0; }
1008题 链接:http://acm.hdu.edu.cn/showproblem.php?pid=5360
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 544 Accepted Submission(s): 290
Special Judge
4 8 4 1 3 2 2 1 0 3 5 3 6 4 2 1 7 6 8 3 3 2 0 5 0 3 6 4 5 2 7 7 6 7 6 8 2 2 3 3 3 0 0 2 7 4 3 6 3 2 2 5 8 5 6 5 3 3 1 2 4 6 7 7 6 5 4 3 5
7 1 7 6 5 2 4 3 8 8 4 6 3 1 2 5 8 7 7 3 6 7 1 5 2 8 4 0 1 2 3 4 5 6 7 8
题意:问邀请的顺序,使得最终去的人最多,每个人有一个区间[l,r]的人数要求
分析:用优先队列维护,按照r从小到大;不是很难注意细节。
#include<stdio.h> #include<queue> #include<algorithm> #include<string.h> using namespace std; const int N = 100005; struct nnn { int l,r,id; }node[N]; struct NNNN { int r,id; friend bool operator<(NNNN aa,NNNN bb) { return aa.r>bb.r; } }; priority_queue<NNNN>q; bool cmp1(nnn aa, nnn bb) { return aa.l<bb.l; } int id[N]; bool vist[N]; int main() { int T,n,ans; NNNN now; scanf("%d",&T); while(T--) { scanf("%d",&n); ans=0; /*for(int i=1; i<=n; i++) printf("%d ",i); printf("=id\n\n");*/ for(int i=0; i<n; i++) { scanf("%d",&node[i].l); node[i].id=i+1; } for(int i=0; i<n; i++) scanf("%d",&node[i].r); sort(node,node+n,cmp1); memset(vist,0,sizeof(vist)); int i=0; while(i<n) { bool ff=0; while(i<n&&ans>=node[i].l&&ans<=node[i].r) { now.r=node[i].r; now.id=node[i].id; q.push(now); //printf("in = %d\n",now.id); i++; ff=1; } if(ff)i--; while(!q.empty()) { now=q.top(); q.pop(); if(now.r<ans)continue; //printf("out = %d\n",now.id); ans++; id[ans]=now.id; vist[now.id]=1; if(node[i+1].l<=ans) break; } i++; } while(!q.empty()) { now=q.top(); q.pop(); if(now.r<ans)continue; //printf("out = %d\n",now.id); ans++; id[ans]=now.id; vist[now.id]=1; } bool fff=0; printf("%d\n",ans); for( i=1; i<=ans; i++) if(i>1) printf(" %d",id[i]); else if(i==1) printf("%d",id[i]); if(ans)fff=1; for( i=1; i<=n; i++) if(vist[i]==0&&fff) printf(" %d",i); else if(vist[i]==0) printf("%d",i),fff=1; printf("\n"); } }
1011题 链接:http://acm.hdu.edu.cn/showproblem.php?pid=5363
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 420 Accepted Submission(s): 275
4 1 2 3 4
0 1 3 7
#include<stdio.h> #define LL long long #define mod 1000000007 LL ppow(LL a,LL b) { LL c=1; while(b) { if(b&1) c=c*a%mod; b>>=1; a=a*a%mod; } return c; } int main() { int T; LL n; scanf("%d",&T); while(T--) { scanf("%lld",&n); printf("%lld\n",ppow(2,n-1)-1); } return 0; }