2017寒假练习题解 第四周 2.6-2.12

Posted 长安大学ACM集训队

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017寒假练习题解 第四周 2.6-2.12相关的知识,希望对你有一定的参考价值。

2.6

Problem A Quasi Binary

题意:给出 n ,输出n至少由k个只含 01的数组成

简析:按照 n 的位数如果相应的一位不是0的话,就填 1 ,再减去,直到减到 n 为0

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<vector>
 6 using namespace std;
 7 
 8 int  n;
 9 int b[1005],a[15],pm[10];
10 
11 void solve(){
12     pm[0]=1;
13     for(int i = 1;i <= 7;i++) pm[i] = pm[i-1]*10;
14     int x = n;
15     vector<int> res;
16     while(n){
17         int c = 0,l = 0;
18         while(x){
19             int tmp = x%10;
20             x = x/10;
21           //  printf("x = %d tmp = %d\\n",x,tmp);
22             if(tmp){
23                 l += pm[c];
24                // printf("--l = %d\\n",l);
25             }
26             c++;
27         }
28        // printf("l = %d\\n",l);
29         res.push_back(l);
30         n -= l;
31         x = n;
32     }
33     printf("%d\\n",res.size());
34     for(int i = 0;i < res.size();i++) printf("%d ",res[i]);
35     printf("\\n");
36 }
37 
38 int main(){
39     while(scanf("%d",&n) != EOF){
40         solve();
41     }
42     return 0;
43 }
参考代码

 

Problem B Tourist\'s Notes

题意:一个人登山 n 天,给出 m 天的di,hi (表示在第di天登山的高度为hi),且 abs(h[i]-h[i-1]) <= 1,问这n天登山的最高高度

简析:假设第 di天的登山高度 为 x,di+1天的登山高度 为 y,这两个日期的时间间隔为 day,假设这两个日期之间能够到达的最大高度为 maxx

如果 x ==  y,

(maxx-x) + (maxx-x) = day

所以 maxx = day/2+x

如果 x > y 或者 x < y

(maxx-x)+(maxx-y) = day

所以 maxx = (day+x+y)/2

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 
 8 const int maxn = 5e5+5;
 9 int n,m;
10 
11 struct node{
12     int d,h;
13 }a[maxn];
14 
15 void solve(){
16     int maxx = -1;
17     for(int i = 1;i <= m+1;i++){
18         if(i == 1){
19             maxx = max(a[i].h+(a[i].d-1),maxx);
20             continue;
21         }
22         if(i == m+1){
23             maxx = max(a[i-1].h+(n-a[i-1].d),maxx);
24             continue;
25         }
26         int x = a[i].h,y = a[i-1].h;
27         int day = a[i].d-a[i-1].d;
28         if(x == y){
29             maxx = max(max(x,maxx),day/2+x);
30             continue;
31         }
32         if(abs(x-y) > day){
33             puts("IMPOSSIBLE");
34             return;
35         }
36         maxx = max(max(x,y),maxx);
37         maxx = max(maxx,(day+x+y)/2);
38     }
39     printf("%d\\n",maxx);
40 }
41 
42 int main(){
43     while(scanf("%d %d",&n,&m) != EOF){
44         for(int i = 1;i <= m;i++) scanf("%d %d",&a[i].d,&a[i].h);
45         solve();
46     }
47     return 0;
48 }
参考代码

 

2.7

Problem A Tavas and SaDDas

题意:问一个数是仅由4和7构成的数中第几小的。

简析:从右往左第ii位对应于2i12i−1,4对应乘1,7对应乘2,让高翔带你自由飞翔吧!

 1 #include<cstdio>
 2 using namespace std;
 3 int main(){
 4     int n,temp=1,ans=0;
 5     scanf("%d",&n);
 6     while(n){
 7         if(n%10==4)
 8             ans+=temp;
 9         else
10             ans+=temp*2;
11         temp*=2;
12         n/=10;
13     }
14     printf("%d",ans);
15     return 0;
16 } 
参考代码

 

Problem B Tavas and Karafs

题意:第ii个迷の棒状物的长度是A+(i1)×BA+(i−1)×B,一次操作是选mm个物体啃掉1,

   给你一个左端点ll,求最大的右端点rr,使得tt次能啃完[l,r][l,r]的物体。

简析:二分右端点。

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 typedef long long LL;
 5 
 6 int main(void)
 7 {
 8     LL A, B, n;
 9     scanf("%I64d %I64d %I64d", &A, &B, &n);
10     while(n--)
11     {
12         LL l, t, m;
13         scanf("%I64d %I64d %I64d", &l, &t, &m);
14         if(A + B * (l - 1) > t) {puts("-1"); continue;}
15         LL L = l, R = 1e7, M;
16         while(L < R)
17         {
18             M = R - (R - L) / 2;
19             LL sum = A * (M - l + 1) + B * (M * (M - 1) - (l - 1) * (l - 2)) / 2;
20             if(A + B * (M - 1) <= t && sum <= m * t) L = M;
21             else R = M - 1;
22         }
23         printf("%I64d\\n", L);
24     }
25     return 0;
26 }
参考代码

 

2.8

Problem A Covered Path

题意:第1秒的速度 为v1,第t秒的速度为v2,每一秒速度的大小的变化最大为 d,问这t秒内走过的最大路程

简析:可以直接算出 vi = min(v1+d*i,v2+d*(t-i-1))

 1 #include<iostream>  
 2 #include<cstdio>  
 3 #include<cstring> 
 4 #include <cmath> 
 5 #include<stack>
 6 #include<vector>
 7 #include<map> 
 8 #include<set>
 9 #include<queue> 
10 #include<algorithm>  
11 using namespace std;
12 
13 typedef long long LL;
14 const int INF = (1<<30)-1;
15 const int mod=1000000007;
16 const int maxn=100005;
17 int v[maxn];
18 
19 int main(){
20     int i,j,a,b,t,d,sum=0;
21     scanf("%d %d",&a,&b);
22     scanf("%d %d",&t,&d);
23     if(d==0) {
24         printf("%d\\n",a+b+a*(t-2));
25         return 0;
26     }
27     v[1]=a;
28     v[t]=b;
29     for(i=2;i<t;i++)
30     v[i]=v[i-1]+d;
31         
32     for(i=t;i>1;i--){
33         if(v[i-1]-v[i]>d){
34             v[i-1]=v[i]+d;
35         }
36     }
37     
38     for(int i=1;i<=t;i++){
39     //    printf("v[%d]=%d\\n",i,v[i]);
40     sum+=v[i];
41     }
42     printf("%d\\n",sum);
43     return 0;
44     
45     
46 }
参考代码

因为 d 值很小,对于每一秒,从 -d 到 d 枚举速度的变化量,只要能够保证能够在剩下的时间里能够减速到v2,就是合法的

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 int main()
 6 {
 7     int v1, v2, t, d;
 8     cin >> v1 >> v2 >> t >> d;
 9 
10     vector<int> v; v.push_back(v1);
11     int now = v1;
12     for(int i = 2; i <= t-1; i++)
13     {
14         int dd;
15         for(dd = d; dd >= -d; dd--)
16             if(now + dd <= (t - i) * d + v2)
17                 break;
18         now += dd;
19         v.push_back(now);
20     }
21     v.push_back(v2);
22     int s = 0;
23     for(int i = 0; i < v.size(); i++) s += v[i];
24     printf("%d\\n", s);
25 
26     return 0;
27 }
参考代码

 

Problem B Polycarpus\' Dice

题意:有 n 个骰子,每个骰子最大的点数为 di,n 个骰子的点数之和为 A,问每个骰子不能够表示的点数的个数

简析:计算每个骰子能够表示的最小点数,最大点数

最小点数可以考虑到其他骰子都为最大值的时候还不够A

最大点数可以考虑到其他骰子点数都不能为0

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 typedef long long LL;
 8 const int maxn = 5e6+5;
 9 int d[maxn],ans[maxn];
10 int n;
11 LL A,sum;
12 
13 void solve(){
14     LL leftsum = 0,minn,maxx;
15     for(int i = 1;i <= n;i++){
16         leftsum = sum-d[i];
17         if(A - leftsum > 0) minn = A-leftsum;
18         else minn = 1;
19         maxx = min(1LL*d[i],A-(n-1));
20 
21              if(minn > maxx) printf("%d ",d[i]-1);
22         else printf("%d ",d[i]-(maxx-minn+1));
23     }
24     printf("\\n");
25 }
26 
27 int main(){
28     while(scanf("%d %I64d",&n,&A) != EOF){
29         sum = 0;
30         for(int i = 1;i <= n;i++) scanf("%d",&d[i]),sum += 1LL*d[i];
31         solve();
32     }
33     return 0;
34 }
参考代码

 

2.9

Problem A Pasha and String

题意:给一个字符串,求m次翻转操作后的字符串。

简析:翻转两次等于没有翻转,所以先标记出所有翻转的位置,最后扫一遍。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 const int maxn = 2e5 + 10;
 7 char s[maxn];
 8 int rev[maxn];
 9 
10 int main(void)
11 {
12     int m, x;
13     scanf("%s %d", s + 1, &m);
14     int l = strlen(s + 1);
15     while(m--)
16     {
17         scanf("%d", &x);
18         rev[x] ^= 1;
19     }
20     int tmp = 0;
21     for(int i = 1; i <= l / 2; i++)
22     {
23         tmp ^= rev[i];
24         if(tmp) swap(s[i], s[l-i+1]);
25     }
26     printf("%s\\n", s + 1);
27     return 0;
28 }
参考代码

 

Problem B Ilya and Sticks

题意:n根棍子,每根棍子可以不变或缩短1,用这些棍子拼矩形,求最大面积和。

简析:排序后从大到小考虑,如果相邻的长度相等或者仅相差1,则将它们作为一对边,

   最后拼矩形的时候长边与长边配对,短边与短边配对,所得的面积和最大。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef long long LL;
 7 const int maxn = 1e5 + 10;
 8 vector<LL> v;
 9 int l[maxn];
10 
11 int main(void)
12 {
13     int n;
14     scanf("%d", &n);
15     for(int i = 0; i < n; i++) scanf("%d", l + i);
16     sort(l, l + n);
17     for(int i = n - 1; i > 0; i--)
18         if(l[i] - l[i-1] < 2)
19             v.push_back(l[i-1]), i--;
20     LL ans = 0, sz = v.size();
21     for(int i = 0; i < sz - 1; i += 2) ans += v[i] * v[i+1];
22     printf("%I64d\\n", ans);
23     return 0;
24 }
参考代码

 

2.10

Problem A Error Correct System

题意:给出两个字符串 s,t 可以交换 s中两个字符的位置,求s,t的最小距离

简析:用 dp[a][b] = i 表示 在第i个位置,s[i] = \'a\' ,t[i] = \'b\',

如果存在 dp[a][b] 和 dp[b][a] ,直接交换这两个字符就好

如果不存在,就交换 dp[a][b] 和dp[b][c]

如果还不存在,就是 -1 ,-1

 1 #include<iostream>  
 2 #include<cstdio>  
 3 #include<cstring> 
 4 #include <cmath> 
 5 #include<stack>
 6 #include<vector>
 7 #include<map> 
 8 #include<queue> 
 9 #include<algorithm>  
10 #define mod=1e9+7;
11 using namespace std;
12 
13 typedef long long LL;
14 const int maxn=200005;
15 char s[maxn],t[maxn];
16 int dp[105][105];
17 int has[maxn];
18 
19 int main(){
20     int i,j,n,ans=0;
21     scanf(寒假每日一题回文平方(个人练习)详细题解+推导证明(第五天)

寒假每日一题总结(第七天)

寒假每日一题翻硬币(个人练习)详细题解+推导证明(第十一天)

寒假每日一题红与黑(个人练习)详细题解+推导证明(第四天)

寒假每日一题总结(第十五天)

寒假每日一题数字三角形(个人练习)详细题解+推导证明(第二天)