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位对应于2i−12i−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+(i−1)×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(寒假每日一题回文平方(个人练习)详细题解+推导证明(第五天)