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("%d",&n);
22     cin>>(s+1)>>(t+1);
23     for(i=1;i<=n;i++){
24         if(s[i]!=t[i]){
25             dp[s[i]-'a'][t[i]-'a']=i;
26             has[s[i]-'a']=i;
27             ans++;
28         }
29     }
30
31     for(i=0;i<26;i++){
32         for(j=0;j<26;j++){
33             if(dp[i][j]!=0&&dp[j][i]!=0){
34                 printf("%d\n",ans-2);
35                 printf("%d %d\n",dp[i][j],dp[j][i]);
36                 return 0;
37             }
38         }
39     }
40
41     for(i=0;i<26;i++){
42         for(j=0;j<26;j++){
43             if(dp[i][j]!=0&&has[j]!=0){
44                 printf("%d\n",ans-1);
45                 printf("%d %d\n",dp[i][j],has[j]);
46                 return 0;
47             }
48         }
49     }
50
51     printf("%d\n",ans);
52     printf("-1 -1\n");
53     return 0;
54 }

参考代码

Problem B Glass Carving

题意:给出一块w*h的玻璃,再切m刀,求每切一刀后,被切割成的玻璃片面积最大的是多少

简析:用一个 multiset 存每次切口的位置,再用一个 multiset 存相邻切口之间的距离

如果当前操作的切口位置 为 x ,在位置集合里找到x 所在的区间 [a,b] ,将x-a,b-x 插入距离集合,同时从距离集合里面删去b-a

每次对应分别取出长和宽距离集合里的最大值相乘

 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<set>
10 #include<algorithm>
11 #define mod=1e9+7;
12 using namespace std;
13
14 typedef long long LL;
15 multiset<int> hh,vv;
16 set<int >ph,qv;
17 set<int>::iterator r,l;
18
19 int main(){
20     char c;
21     int x,w,h,n;
22     scanf("%d%d%d",&w,&h,&n);getchar();
23     ph.insert(0);ph.insert(h);
24     qv.insert(0);qv.insert(w);
25     hh.insert(h);vv.insert(w);
26
27     while(n--){
28         scanf("%c %d",&c,&x);getchar();
29
30         if(c == 'H')
31         {
32             l = ph.lower_bound(x);
33             r = l; l--;
34             ph.insert(x);
35             hh.insert(x-(*l));
36             hh.insert((*r)-x);
37             hh.erase(hh.find((*r) - (*l)));
38         }
39         else
40         {
41             l = qv.lower_bound(x);
42             r = l; l--;
43             qv.insert(x);
44             vv.insert(x - (*l));
45             vv.insert((*r) - x);
46             vv.erase(vv.find((*r) - (*l)));
47         }
48
49         printf("%I64d\n", (long long)(*hh.rbegin()) * (*vv.rbegin()));
50
51
52     }
53     return 0;
54 }

参考代码

2.11

Problem A Two Buttons

题意:给n,m两个数,一次操作是将n减一或者乘二,问把n变为m最少要几步。

简析:因为n与m的范围都很小,所以可以无脑のBFS一下。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <queue>
 4 #include <set>
 5 using namespace std;
 6 typedef pair<int, int> pii;
 7
 8 int main(void)
 9 {
10     int n, m;
11     scanf("%d %d", &n, &m);
12     set<int> s;
13     queue<pii> q;
14     s.insert(n);
15     q.push(pii(n, 0));
16     while(!q.empty())
17     {
18         pii tmp = q.front(); q.pop();
19         int cur = tmp.first, t = tmp.second;
20         if(cur == m) {printf("%d\n", t); break;}
21         if(cur > 1 && !s.count(cur-1)) s.insert(cur-1), q.push(pii(cur-1, t+1));
22         if(cur < m && !s.count(cur*2)) s.insert(cur*2), q.push(pii(cur*2, t+1));
23     }
24     return 0;
25 }

参考代码

Problem B DNA Alignment

题意:问存在多少个不同的字符串t,使得对于已定义的:

   

   满足

   

   其中shift表示左移1个字符,h表示相同位置字符相同数。

简析:先考虑这个和式的意义,用s_cnt[A]表示A在s中出现的次数,其他类似的表示,

显然原式等价于n * ( s_cnt[A] * t_cnt[A] + s_cnt[T] * t_cnt[T] + s_cnt[C] * t_cnt[C] + s_cnt[G] * t_cnt[G] ) 
那么对于已知的s,如何构造t让这个和尽量大呢?
显然只要让t中的所有字符都为s中出现次数最多的那个即可,如果s中有多个字符次数同时最多,则均可选择。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long LL;
 6 const LL mod = 1e9 + 7;
 7 const int maxn = 1e5 + 10;
 8 char s[maxn];
 9 int cnt[4];
10
11 LL qpow(LL a, int b)
12 {
13     LL ret = 1LL;
14     while(b)
15     {
16         if(b & 1) ret = ret * a % mod;
17         a = a * a % mod;
18         b >>= 1;
19     }
20     return ret;
21 }
22
23 int main(void)
24 {
25     int n;
26     scanf("%d%s", &n, s);
27     for(int i = 0; i < n; i++)
28     {
29         if(s[i] == 'A') cnt[0]++;
30         else if(s[i] == 'G') cnt[1]++;
31         else if(s[i] == 'C') cnt[2]++;
32         else cnt[3]++;
33     }
34     sort(cnt, cnt + 4);
35     int tot = 1;
36     for(int i = 0; i < 3; i++) tot += cnt[i] == cnt[3];
37     printf("%I64d\n", qpow(tot, n));
38     return 0;
39 }

参考代码

2.12

Problem A A and B and Compilation Errors

题意:第一行 n 个数 a[i],第二行 n-1个数b[i],第三行 n-2个数 c[i],求第二行比第一行少的那个数,第三行比第二行少的那个数

简析:第一行的和为 A,第二行的和为 B,第三行的和为 C,所以为 A-B,B-C

 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 = 5e5+5;
 9 int a[maxn],b[maxn],c[maxn];
10 int n;
11
12 int main(){
13     while(scanf("%d",&n) != EOF){
14         LL A = 0,B = 0,C = 0;
15         for(int i = 1;i <= n;i++){
16             scanf("%d",&a[i]);
17             A += 1LL*a[i];
18         }
19         for(int i = 1;i <= n-1;i++){
20             scanf("%d",&b[i]);
21             B += 1LL*b[i];
22         }
23         for(int i = 1;i <= n-2;i++){
24             scanf("%d",&c[i]);
25             C += 1LL*c[i];
26         }
27         printf("%I64d\n%I64d\n",A-B,B-C);
28     }
29     return 0;
30 }

参考代码

Problem B A and B and Team Training

题意:有n个A和 m个B,可以一个A两个B一队,也可以两个A一个B一队,求最多能够组成多少队

简析:先要满足 n+m >= 3才能组成一队,然后如果 n 更大,就组成两个A一个B一队,如果m更大,就组成一个A两个B一队

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6
 7 int n,m;
 8
 9 int main(){
10     while(scanf("%d %d",&n,&m) != EOF){
11         printf("%d\n",min(min(n,m),(n+m)/3));
12     }
13     return  0;
14 }

参考代码

转载于:https://www.cnblogs.com/chdacm/p/6372921.html

2017寒假练习题解 第四周 2.6-2.12相关推荐

  1. COCI 2016/2017 Round #3 题解

    COCI 2016/2017 Round #3 这套题代码量似乎有些大呀...前五题代码都已经破4KB了... 而且还要卡空间.卡常数... Imena 题目翻译 分析 细节模拟题,注意可能会出现名字 ...

  2. CCF 2017年题目题解 - Python

    2017年刷题目录 2017年12月 201712-1 最小差值 题目链接: 代码: 易错点需注意点: 201712-2 游戏 题目链接: 代码: 易错点需注意点:直接模拟! 201712-3 题目链 ...

  3. 2017寒假作业 计科1501 李俊01

    寒假预留作业1 1.阅读邹欣老师的博客,谈谈你期望的师生关系是什么样的? 从小到大,遇到过不少老师,我最希望的和邹欣老师一样是健身教练和健身学员的关系,教练本身应该在所教的项目中是很有经验的身体力行者 ...

  4. 寒假“最小生成树”题解

    1.P3366 [模板]最小生成树 题目描述 如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz. 输入格式 第一行包含两个整数 N,M,表示该图共有 N 个结点和 M 条无向边. ...

  5. [赛后总结]COCI2016/2017 Round#3题解

    文章目录 Imena 题面 描述 输入 输出 分数分布 题解 实现 Pohlepko 题面 描述 输入 输出 分数分布 题解 实现 Kronican 题面 描述 输入 输出 分数分布 题解 实现 Kv ...

  6. LSNU寒假集训 题解

    目录 LSNU寒假第一场(基础算法+几何) A - Fifa and Fafa B - Anton and Lines C - Minimum path D - Thematic Contests E ...

  7. [赛后总结]COCI2016/2017 Round#2题解

    文章目录 Go 题面 描述 输出 分数分布 题解 实现 Tavan 题面 描述 输入 输出 分数分布 题解 实现 Nizin 题目 描述 输入 输出 分数分布 题解 实现 Prosjecni 题目 描 ...

  8. COCI 2016/2017 Round #5题解

    COCI 2016/2017 Round #5 Tuna 题目翻译 分析 水题,按题意模拟即可. 参考代码 #include<cstdio> #include<algorithm&g ...

  9. 2017寒假第一篇随笔(寒假作业一)

    在人生技能道路上,你有没有专长的高超技能获取的成功经验? 在高中时没有过多的兴趣爱好,只是喜欢在闲暇之余看一集美剧,长时间处于美式英语的"熏陶"之下,自然对英语产生了浓厚的兴趣,在 ...

最新文章

  1. 【c语言】蓝桥杯算法训练 整数平均值
  2. pig 的chararry类型不能用比较运算符comparison operator
  3. FlexViewer入门资料
  4. 全国计算机等级考试题库二级C操作题100套(第65套)
  5. childnodes 兼容性问题
  6. java实现多对多关系的方法_Hibernate一对多关联双向关联代码实现分享
  7. 【C++】错误处理和异常处理
  8. it男java_java-学习8
  9. oc渲染器中文手册_C4D·OC高级渲染视频教程,带你玩转质感渲染
  10. python统计时间的次数的代码_python脚本实现统计日志文件中的ip访问次数代码分享...
  11. static 在C/C++中的用法总结
  12. python爬虫框架论文开题报告范文_论文开题报告框架
  13. 10mbps 局域网组播_80211 组播速率及组播转单播
  14. c++获取电脑mac地址
  15. Hand Crafted 特征 PK 纯学习的特征提取方法
  16. linux文件操作命令包括,学习Linux命令之最基本的文件操作
  17. shell for循环命令行_七年老运维实战中的 Shell 开发经验总结
  18. vue中前端实现pdf预览(含vue-pdf插件用法)
  19. 论文阅读——Updatable Learned Index with Precise Positions(VLDB‘21)
  20. #8 实现指定函数swap(结构体)

热门文章

  1. Spring Boot错误处理机制以及定制自己的错误页面
  2. MATLAB常用命令(窗口命令、标点符号特殊功能和帮助命令)
  3. 4.6 matlab图形修饰处理(视点处理、色彩处理、裁剪处理)
  4. 网络状态代码数字的含义
  5. 2019年财政收支分析_2019年CPI走势预测与分析
  6. linux升级Python2.7.12
  7. MATLAB环境认识实验报告,matlab实验报告ljg
  8. 滚动条全局样式修改与局部修改
  9. Docker Machine 简介
  10. 在Linux系统安装Nodejs 最简单步骤