CHD 2015迎新杯题解

A.预防流感的拉面女神

简析:计算 n 的二进制表示里面 1 的个数

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 int bitcount(int x) {
 7     int ans = 0;
 8     while(x) {
 9         if(x & 1) ans++;
10         x >>= 1;
11     }
12     return ans;
13 }
14 
15 int main()
16 {
17 //    freopen("in.txt", "r", stdin);
18 //    freopen("out.txt", "w", stdout);
19 
20     int T; scanf("%d", &T);
21     while(T--) {
22         int n; scanf("%d", &n);
23         printf("%d\n", bitcount(n));
24     }
25 
26     return 0;
27 }
参考代码

 

B.草滩小王子与天行健

简析:这个题主要分成四种情况讨论:

一荤一素,两荤两素,一素两荤,一荤两素。

因为不管是饭和汤,还是面条,都会对应上面四种情况,所以我把饭和汤,面条写的一个函数里。

详细见代码,请各位大神指教。----wzm

 1 #include <iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 int a[15],b[15],c[15],d[15],e[15];
 7 int a1,b1,c1,d1,e1;
 8 int sum[5],ans,minn,maxn;
 9 void f(int s){//一饭一汤,面条
10     for(int x = 1; x<=a1; x++){
11         for(int y = 1; y<=b1; y++){
12             if((s+a[x]+b[y])>=minn&&(s+a[x]+b[y])<=maxn){
13                 ans++;
14             }
15         }
16     }
17     for(int z = 1; z<=c1; z++){
18         if((s+c[z])>=minn&&(s+c[z])<=maxn){
19             ans++;
20         }
21     }
22 }
23 void solve(){
24     int t;
25     scanf("%d",&t);
26     while(t--){
27         cin>>a1>>b1>>c1>>d1>>e1;
28         for(int i = 1; i<=a1; i++) cin>>a[i];
29         for(int i = 1; i<=b1; i++) cin>>b[i];
30         for(int i = 1; i<=c1; i++) cin>>c[i];
31         for(int i = 1; i<=d1; i++) cin>>d[i];
32         for(int i = 1; i<=e1; i++) cin>>e[i];
33         cin>>minn>>maxn;
34         ans = 0;
35         for(int i = 1; i<=d1; i++){//一荤一素
36             for(int j = 1; j<=e1; j++){
37                 {
38                     int s = d[i]+e[j];
39                     f(s);
40                 }
41             }
42         }
43         for(int i = 1; i<=d1; i++)//两荤两素
44         for(int j = i+1; j<=d1; j++){
45             for(int p = 1; p<=e1; p++){
46                 for(int q = p+1; q<=e1; q++){
47                     int s = d[i]+d[j]+e[p]+e[q];
48                     f(s);
49                 }
50             }
51         }
52         for(int i = 1; i<=d1; i++){//一荤两素
53             for(int p = 1; p<=e1; p++)
54                 for(int q = p+1; q<=e1; q++){
55                     int s = d[i]+e[p]+e[q];
56                     f(s);
57                 }
58         }
59         for(int p = 1; p<=e1; p++){//两荤一素
60             for(int i = 1;i<=d1; i++){
61                 for(int j = i+1; j<=d1; j++){
62                     int s = d[i]+d[j]+e[p];
63                     f(s);
64                 }
65             }
66         }
67         printf("%d\n",ans);
68     }
69 }
70 int main()
71 {
72     solve();
73     return 0;
74 }
wzm

 

 C.草滩小王子与测量误差

简析:可以先将角度转换为最小的单位的值,再按照题意模拟

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<cmath>
  6 using namespace std;
  7 
  8 struct Node{
  9     int d,m,s;
 10     int x;
 11 }a[55];
 12 
 13 struct node{
 14     double l;
 15     int id;
 16 }b[55];
 17 
 18 int cmp(node n1,node n2){
 19     return n1.l < n2.l;
 20 }
 21 
 22 int sum,vis[55],n;
 23 double len[55];
 24 
 25 void solve(){
 26     int sum0 = (n-2)*180*3600;
 27     int f = sum - sum0;
 28     if( (long long) f*f > 1600*n){
 29         puts("Poor Prince Cao Tan");
 30         return;
 31     }
 32     f = -f;
 33     int v = f/n;
 34     int r = f%n;
 35    // printf("v = %d  r = %d\n",v,r);
 36     memset(vis,0,sizeof(vis));
 37     sort(b+1,b+n+1,cmp);
 38     for(int i = 1;i <= n;i++){
 39         int bl,br,jl,jr;
 40         if(b[i].id == n){
 41             bl = 1;
 42             br = n-1;
 43             jl = 1;
 44             jr = n;
 45         }
 46         else if(b[i].id == 1){
 47             bl = n;
 48             br = 2;
 49             jl = 1;
 50             jr = 2;
 51         }
 52         else{
 53             bl = b[i].id -1;
 54             br = b[i].id +1;
 55             jl = b[i].id;
 56             jr = b[i].id+1;
 57         }
 58         if(len[bl] > len[br]){
 59             swap(bl,br);
 60             swap(jl,jr);
 61         }
 62      //   printf("bl = %d  br = %d  jl = %d  jr = %d\n",bl,br,jl,jr);
 63                 if(!vis[jl]){
 64                     a[jl].x += v;
 65                     if(abs(r)){
 66                         a[jl].x += r/abs(r);
 67                         int fuhao = r/abs(r);
 68                         if(fuhao == -1) r++;
 69                         else r--;
 70                     }
 71                     vis[jl] = 1;
 72                 }
 73                 if(!vis[jr]){
 74                     a[jr].x += v;
 75                     if(abs(r)){
 76                         a[jr].x += r/abs(r);
 77                         int fuhao = r/abs(r);
 78                         if(fuhao == -1) r++;
 79                         else r--;
 80                     }
 81                     vis[jr] = 1;
 82                 }
 83     }
 84     for(int i = 1;i <= n;i++){
 85         int c1 = a[i].x/3600;
 86         int c2 = (a[i].x-c1*3600)/60;
 87         int c3 = a[i].x-c1*3600-c2*60;
 88         a[i].d = c1;a[i].m = c2;a[i].s = c3;
 89     }
 90     for(int i = 1;i <= n;i++) printf("%d %d %d\n",a[i].d,a[i].m,a[i].s);
 91 }
 92 
 93 int main(){
 94     int T;
 95     scanf("%d",&T);
 96     while(T--){
 97         scanf("%d",&n);
 98         sum = 0;
 99         for(int i = 1;i <= n;i++){
100             scanf("%d %d %d",&a[i].d,&a[i].m,&a[i].s);
101             a[i].x = a[i].d*3600 + a[i].m*60+a[i].s;
102             sum += a[i].x;
103         }
104         for(int i = 1;i <= n;i++){
105             scanf("%lf",&b[i].l);
106             b[i].id = i;
107             len[i] = b[i].l;
108         }
109         solve();
110     }
111     return 0;
112 }
参考代码1
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <cmath>
  6 using namespace std;
  7 const int maxn=20;
  8 double L[maxn];
  9 
 10 struct angle
 11 {
 12     int d,m,s;
 13 }Zero,One,b[maxn],v[maxn],a[maxn];
 14 
 15 angle Plus(angle A,angle B)
 16 {
 17     angle tmp=Zero;
 18     tmp.s=A.s+B.s;
 19     if(tmp.s>=60) tmp.s-=60,tmp.m++;
 20     tmp.m+=A.m+B.m;
 21     if(tmp.m>=60) tmp.m-=60,tmp.d++;
 22     tmp.d+=A.d+B.d;
 23     return tmp;
 24 }
 25 
 26 angle Minus(angle A,angle B)
 27 {
 28     angle tmp;
 29     tmp.s=A.s-B.s;
 30     tmp.m=A.m-B.m;
 31     tmp.d=A.d-B.d;
 32     while(tmp.s<0) tmp.s+=60,tmp.m--;
 33     while(tmp.m<0) tmp.m+=60,tmp.d--;
 34     return tmp;
 35 }
 36 
 37 angle Divide(angle A,int B)
 38 {
 39     angle tmp;
 40     tmp.d=A.d/B;
 41     tmp.m=A.m+A.d%B*60;
 42     tmp.s=A.s+tmp.m%B*60;
 43     tmp.m/=B;
 44     tmp.s/=B;
 45     return tmp;
 46 }
 47 
 48 angle Mod(angle A,int B)
 49 {
 50     angle tmp;
 51     tmp.s=(A.d*3600+A.m*60+A.s)%B;
 52     return tmp;
 53 }
 54 
 55 bool Smaller(angle A,angle B)
 56 {
 57     if(A.d!=B.d) return A.d<B.d;
 58     if(A.m!=B.m) return A.m<B.m;
 59     return A.s<B.s;
 60 }
 61 
 62 struct point
 63 {
 64     int id;
 65     double x,y;
 66 }p[maxn];
 67 
 68 bool cmp(point A,point B)
 69 {
 70     if(A.x!=B.x) return A.x<B.x;
 71     return A.y<B.y;
 72 }
 73 
 74 int main(void)
 75 {
 76     int T;
 77     scanf("%d",&T);
 78     Zero.d=Zero.m=Zero.s=0;
 79     One.d=One.m=0;One.s=1;
 80     while(T--)
 81     {
 82         int n,flag=0;
 83         scanf("%d",&n);
 84         angle sum=Zero,tot=Zero,delta,q,r;
 85         for(int i=1;i<=n;i++)
 86         {
 87             scanf("%d%d%d",&b[i].d,&b[i].m,&b[i].s);
 88             sum=Plus(sum,b[i]);
 89         }
 90         for(int i=1;i<=n;i++) scanf("%lf",L+i);
 91         tot.d=(n-2)*180;
 92         if(Smaller(sum,tot)) {flag=1; delta=Minus(tot,sum);}
 93         else delta=Minus(sum,tot);
 94         if(delta.d*3600+delta.m*60+delta.s>40*sqrt(n)) {puts("Poor Prince Cao Tan");continue;}
 95         q=Divide(delta,n);
 96         r=Mod(delta,n);
 97         for(int i=1;i<=n;i++)
 98         {
 99             double x=L[i],y=L[i-1<1?n:i-1];
100             if(x>y) swap(x,y);
101             p[i].id=i;
102             p[i].x=x;
103             p[i].y=y;
104         }
105         sort(p+1,p+1+n,cmp);
106         memset(v,0,sizeof(v));
107         for(int i=1;i<=n;i++)
108         {
109             if(!Smaller(Zero,r)&&!Smaller(r,Zero)) break;
110             int pos=p[i].id;
111             v[pos]=Plus(v[pos],One);
112             r=Minus(r,One);
113         }
114         for(int i=1;i<=n;i++)
115         {
116             if(flag) a[i]=Plus(Plus(b[i],v[i]),q);
117             else a[i]=Minus(Minus(b[i],v[i]),q);
118             printf("%d %d %d\n",a[i].d,a[i].m,a[i].s);
119         }
120     }
121     return 0;
122 }
参考代码2

 

D.无奈自习的草滩小王子

简析:dp[i] 表示花费 i 时间做事情能够得到的最大效率,最后再 O(n) 扫一遍 (t-i) * (dp[i] + 1) 得到最大值

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int MAXT=1e3+10;
 6 int dp[MAXT];
 7 int main(){
 8     int T;
 9     scanf("%d",&T);
10     while(T--){
11         int n,t;
12         scanf("%d%d",&t,&n);
13         memset(dp,0,sizeof(dp));
14         for(int i=1;i<=n;i++) {
15             int a,b;
16             scanf("%d%d",&a,&b);
17             for(int j=t;j>=a;j--)dp[j]=max(dp[j],dp[j-a]+b);
18         }
19         int ans=0;
20         for(int i=0;i<t;i++) ans=max(ans,(t-i)*( dp[i]+1) );
21         printf("%d\n",ans);
22     }
23     return 0;
24 }
参考代码

 

E.草滩小王子之化学实验课

简析:用并查集处理每一对能够发生化学反应的药剂,反应次数,

假设一个连通块的大小为 x ,则发生化学反应的次数为 x-1 (x >= 2)将所有的连通块的反应次数加起来即可

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <vector>
 6 #include <bitset>
 7 #include <cmath>
 8 using namespace std;
 9 
10 int s[1000010];
11 
12 int Find(int x)
13 {
14     if(s[x] == 0) return x;
15     return s[x] = Find(s[x]);
16 }
17 
18 void SetUnion(int r1, int r2)
19 {
20     s[r2] = r1;
21 }
22 
23 int main()
24 {
25     int t, n, k;
26     int x, y;
27     int r1, r2;
28     int ans;
29     scanf("%d", &t);
30     while(t--)
31     {
32         ans = 0;
33         memset(s, 0, sizeof(s));
34         scanf("%d%d", &n, &k);
35         for(int i = 1 ; i <= k ; i++)
36         {
37             scanf("%d%d", &x, &y);
38             r1 = Find(x);
39             r2 = Find(y);
40             if(r1 != r2)
41             {
42                 SetUnion(r1, r2);
43             }
44         }
45         for(int i = 1 ; i <= n ; i++)
46             if(s[i] == 0) ans++;
47         ans = n - ans;
48         printf("%d\n",ans);
49     }
50     return 0;
51 }
参考代码

 

F.草滩小王子与打扫宿舍

简析:巴什博奕 戳这

 1 #include <cstdio>
 2 
 3 int main()
 4 {
 5     //freopen("in.txt", "r", stdin);
 6     //freopen("out.txt", "w", stdout);
 7 
 8     int T; scanf("%d", &T);
 9     while(T--) {
10         int n, m;
11          scanf("%d%d", &n, &m);
12         if(n % (m + 1) == 0) printf("Bob\n");
13         else printf("Alex\n");
14     }
15     return 0;
16 }
参考代码

 

G.草滩小王子与黄牛票

简析:倒着扫一遍,维护一个最大值max,如果当前的 a[i] > max ,更新 max 的值,

否则将 a[i] 卖掉,得到 max-a[i] 的钱

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 typedef long long LL;
 5 const int maxn = 1e6 + 10;
 6 LL a[maxn];
 7 
 8 int main(void)
 9 {
10     int T;
11     scanf("%d",&T);
12     while(T--)
13     {
14         int N;
15         scanf("%d",&N);
16         for(int i = 1; i <= N; i++) scanf("%I64d",a+i);
17         LL ans = 0LL, Max = 0LL;
18         for(int i = N; i >= 1; i--)
19         {
20             if(a[i] > Max) Max = a[i];
21             else ans += Max - a[i] ;
22         }
23         printf("%I64d\n",ans);
24     }
25     return 0;
26 }
参考代码

 

H.拉面女神的生日派对

简析:二分每个人分到的蛋糕大小 x ,每次check 能够分出的块数 tot 是否 >= n

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <ctime>
 5 using namespace std;
 6 
 7 const int maxn = 20000 + 10;
 8 const int INF = 0x3f3f3f3f;
 9 
10 int n, m;
11 int a[maxn];
12 
13 bool check(int x) {
14     long long tot = 0;
15     for(int i = 0; i < m; i++) {
16         tot += a[i] / x;
17     }
18     return tot >= n;
19 }
20 
21 int main()
22 {
23 //    freopen("in.txt", "r", stdin);
24 //    freopen("out.txt", "w", stdout);
25 
26     int T; scanf("%d", &T);
27     while(T--) {
28         scanf("%d%d", &n, &m);
29         for(int i = 0; i < m; i++) scanf("%d", a + i);
30 
31         if(!check(1)) {
32             printf("0\n");
33             continue;
34         }
35 
36         int L = 1, R = INF;
37         while(L < R) {
38             int mid = (L + R) / 2 + 1;
39             if(check(mid)) L = mid;
40             else R = mid - 1;
41         }
42 
43         printf("%d\n", L);
44     }
45 
46 //  printf("Time used = %.3f\n", (double)clock() / CLOCKS_PER_SEC);
47     return 0;
48 }
参考代码

 

I.拉面女神的魔盒

简析:  按照题意bfs,状态数不会超过1e6 ,所以可以bfs一遍预处理出所有的答案

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <queue>
  5 #include <algorithm>
  6 using namespace std;
  7 const int maxn = 1000000;
  8 typedef pair<int, int> pii;
  9 int tmp[7], cur[7], ans[maxn];
 10 
 11 int id(int * a)
 12 {
 13     int ret = a[1];
 14     for(int i = 2; i <= 6; i++)
 15         ret = ret * 10 + a[i];
 16     return ret;
 17 }
 18 
 19 void change(int no)
 20 {
 21     for(int i = 6; i >= 1; i--)
 22         cur[i] = no % 10, no /= 10;
 23     return;
 24 }
 25 
 26 void BFS()
 27 {
 28     queue<pii> q;
 29     q.push(pii(0,0));
 30     ans[0] = 0;
 31     while(!q.empty())
 32     {
 33         pii tmp = q.front(); q.pop();
 34         int now = tmp.first, t = tmp.second;
 35         change(now);
 36         int Next, n[7], sum = 0, odd = 0;
 37         memcpy(n, cur, sizeof(n));
 38         for(int i = 1; i <= 6; i++)
 39         {
 40             sum += cur[i];
 41             if(cur[i] % 2) odd++;
 42         }
 43 
 44         n[1] = (cur[1] + 1) % 10;
 45         Next = id(n);
 46         if(ans[Next] == -1){q.push(pii(Next, t+1)); ans[Next] = t + 1;}
 47 
 48         n[1] = (cur[1] + 9) % 10;
 49         Next = id(n);
 50         if(ans[Next] == -1){q.push(pii(Next, t+1)); ans[Next] = t + 1;}
 51 
 52         n[1] = cur[1];
 53 
 54         if(odd == 3)
 55         {
 56             n[2] = (cur[2] + 1) % 10;
 57             Next = id(n);
 58             if(ans[Next] == -1){q.push(pii(Next, t+1)); ans[Next] = t + 1;}
 59 
 60             n[2] = (cur[2] + 9) % 10;
 61             Next = id(n);
 62             if(ans[Next] == -1){q.push(pii(Next, t+1)); ans[Next] = t + 1;}
 63 
 64             n[2] = cur[2];
 65         }
 66 
 67         n[3] = (cur[3] + 7) % 10;
 68         Next = id(n);
 69         if(ans[Next] == -1){q.push(pii(Next, t+1)); ans[Next] = t + 1;}
 70         n[3] = cur[3];
 71 
 72         n[4] = (cur[4] +  (sum % 9 + 1) ) % 10;
 73         Next = id(n);
 74         if(ans[Next] == -1){q.push(pii(Next, t+1)); ans[Next] = t + 1;}
 75         n[4] = cur[4];
 76 
 77         if(cur[1] + cur[3] + cur[5] == 9)
 78         {
 79             n[5] = (cur[5] + 1) % 10;
 80             Next = id(n);
 81             if(ans[Next] == -1){q.push(pii(Next, t+1)); ans[Next] = t + 1;}
 82 
 83             n[5] = (cur[5] + 9) % 10;
 84             Next = id(n);
 85             if(ans[Next] == -1){q.push(pii(Next, t+1)); ans[Next] = t + 1;}
 86 
 87             n[5] = cur[5];
 88         }
 89 
 90         if(cur[2] == 0)
 91         {
 92             n[6] = (cur[6] + 7) % 10;
 93             Next = id(n);
 94             if(ans[Next] == -1){q.push(pii(Next, t+1)); ans[Next] = t + 1;}
 95         }
 96 
 97     }
 98     return;
 99 }
100 
101 int main(void)
102 {
103    // freopen("in.txt","r",stdin);
104     //freopen("out.txt","w",stdout);
105     memset(ans, -1, sizeof(ans));
106     BFS();
107     int T;
108     scanf("%d", &T);
109     while(T--)
110     {
111         for(int i = 1; i <= 6; i++) scanf("%d", tmp + i);
112         printf("%d\n", ans[id(tmp)]);
113     }
114     return 0;
115 }
参考代码

 

J.草滩小王子与炫酷魔方

简析:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

~end~

posted @ 2016-04-15 23:24  长安大学ACM集训队  阅读(351)  评论(0编辑  收藏  举报