牛客小白月赛16练习

 

 


 

G-小石的图形

链接:https://ac.nowcoder.com/acm/contest/949/G
来源:牛客网

题目描述

小石想在一面墙旁边建造一段长度为 n 的篱笆来围出一块地(如图)。



求最大的地的面积。

输入描述:

共一行,输入一个整数 n 。

输出描述:

共一行,输出最大面积,保留 3 位小数。

示例1

输入

1

输出

0.159

备注:

0n103

一看就是水题,上网搜了下π的取值,3.1415926535898,同学用的3.1415926wa掉了

发现半圆时面积最大(显然)。 n=πR,R=n/π
面积S=πR2/2=n2/2π

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <math.h>
 4 #include <algorithm>
 5 using namespace std;
 6 #define PI 3.1415926535898
 7  
 8 int main()
 9 {
10     int n;
11     scanf("%d",&n);
12     printf("%.3f\n",pow(n,2)/(2*PI));
13     return 0;
14 }

 


 

E-小雨的矩阵

链接:https://ac.nowcoder.com/acm/contest/949/E
来源:牛客网

题目描述

小雨有一个 n×n 的矩阵,起点在(1,1),终点在(n,n),只能向下或向右走,且每次只能走 1 步。矩阵上每个点都有一个点权 ai,j
求走到终点的路径有多少不同的点权和。

输入描述:

第一行,输入一个正整数 n 。
接下来 n+1 行,每行 n 个数,表示 ai,j

输出描述:

共一行,输出有多少不同的点权和。

示例1

输入

2
1 5
2 4

输出

2

说明

(1,1)(2,1)(2,2)7(1,1)(1,2)(2,2)10

备注:

1n8,0ai,j50

刚开始以为很难,后来发现也就是一道水题,从(1,1)爆搜到(n,n),把答案去一下重即可。

用DFS,结果存到set中就好了

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <set>
 4 using namespace std;
 5  
 6 int N[9][9];
 7 int T[2][2]={{0,1},{1,0}};
 8 int vis[9][9];
 9 int n;
10  
11 set<int> st;
12  
13 void DFS(int x,int y,int sum)
14 {
15      
16     if(x==n&&y==n)
17     {
18         st.insert(sum);
19         return;
20     }
21     for(int i=0;i<2;i++)
22     {
23         int a=x+T[i][0];
24         int b=y+T[i][1];
25         if(a<1||b<1||a>n||b>n)
26             continue;
27         if(!vis[a][b])
28         {
29             vis[a][b]=1;
30             DFS(a,b,sum+N[a][b]);
31             vis[a][b]=0;
32         }
33     }
34     return;
35 }
36  
37 int main()
38 {
39     scanf("%d",&n);
40     for(int i=1;i<=n;i++)
41     {
42         for(int j=1;j<=n;j++)
43         {
44             scanf("%d",&N[i][j]);      
45         }
46     }
47     DFS(1,1,N[1][1]);
48     printf("%d",st.size());
49     return 0;
50 }

 


 

A-小石的签到题

链接:https://ac.nowcoder.com/acm/contest/949/A
来源:牛客网

题目描述

小石和小阳玩游戏,一共有 n个数,分别为 1n。两人轮流取数,小石先手。对于每轮取数,都必须选择剩下数中的任意一个数 x,同时还要取走 x,x/2,x/2⌋/2… 如果某个数不存在,就停止取数(不能一个数都不取)。
谁取走最后一个数,谁就输了。小石想知道自己能否获胜。 如果小石能赢,输出 “Shi”,否则输出 "Yang”(均不输出引号)。

输入描述:

共一行,输入一个数 n

输出描述:

共一行,输出 "Shi" 或 "Yang"(不输出引号)。

示例1

输入

1

输出

Yang

说明

小石只能取走 11,小阳赢。

示例2

输入

2

输出

Shi

说明

若小石取走 11,则小阳只能取走 22,小石赢。

备注:

1n109

 

第一题看到别人几分钟就做出来了,很是懵逼,想不出为什么呀。。。估计可能是规律题,要猜猜

第一次是猜奇数小阳赢,偶数小石赢,错了。

后来发现当 n>1 时先手(小石)总是赢。 如何证明:一开始有 1n , n 个数,假设先手必败,那么先手选 1,后手就进入了必败状态。
所以假设错误,那么先手就不是必败,先手一定有一种方式能赢。

 怪不得有人四十多秒就做出来。。

 1 #include<stdio.h>
 2 
 3 int main()
 4 {
 5     int n;
 6     scanf("%d",&n);
 7     if(n==1)
 8         printf("Yang\n");
 9     else
10         printf("Shi\n");
11     return 0;
12 }

 


 

C-小石的海岛之旅

链接:https://ac.nowcoder.com/acm/contest/949/C
来源:牛客网

题目描述

暑假到了,小石和小雨到海岛上玩。
从水平方向看海岛可以看成 n个小块,每一个小块都有一个高度hi
水位一开始为 0,随着水位的上升,海岛分成了若干块。
现在有 m 个询问,求当水位为ai 时,海岛会分成多少块。
 

输入描述:

第一行输入两个正整数n,m,分别表示海岛小块个数和询问个数。
第二行输入 n 个整数 hi,表示每一块的高度。
第三行输入 m个整数 ai,表示每一个询问,保证输入的 ai 单调递增。

输出描述:

共 m 行,分别对应 m 个询问的答案。

示例1

输入

7 3
1 2 3 1 2 1 3
1 2 3

输出

3
2
0

说明

当水位高度为 1 时,岛屿被分成 3 块,2 3;2;3

当水位高度为 2 时,岛屿被分成 2 块:3;3 。

当水位高度为 3 时,岛屿全部被淹没,剩余 0 块 。

备注:

1n,m103,1hi109,1ai<ai+1109

我们按海岛的高度 hi 从大到小排序。
假设海岛i在水位为 ai 时被淹没,如果海岛 i1 和海岛 i+1 都已被淹没,那么就少了一块,答案减 1 。
如果海岛 i1 和海岛 i+1 都没被淹没,那么一块变两块,答案加 1 。
否则答案不变。
由于出题人良心,直接N2是能过的。

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <iostream>
 4 #include <string>
 5 #include <math.h>
 6 #include <algorithm>
 7 #include <queue>
 8 using namespace std;
 9 #define maxn 1002
10 int D[maxn];
11 int F[maxn];
12 int main()
13 {
14     //freopen("sample.txt","r",stdin);
15     int n,m;
16     scanf("%d %d",&n,&m);
17     for(int i=1;i<=n;i++)
18     {
19         scanf("%d",&D[i]); 
20     }
21     memset(F,1,sizeof(F));
22     F[n+1]=0;
23     for(int i=0;i<m;i++)
24     {
25         int t;
26         scanf("%d",&t);
27         for(int j=1;j<=n;j++)
28         {
29             if(F[j]&&D[j]<=t)
30             {
31                 F[j]=0;
32             }
33         }
34         int tot=0;
35         for(int j=1;j<=n;j++)
36         {
37             if(F[j]&&!F[j+1])
38             {
39                 tot++;
40             }
41         }
42         printf("%d\n",tot);
43     }
44     return 0;
45 }

 

 


 

B-小雨的三角形

链接:https://ac.nowcoder.com/acm/contest/949/B
来源:牛客网

题目描述

小雨手上有一个填满了数字的三角形。这个三角形一共有 n 层,其中第 i 层共有 i个数,且第 1 个数和第 i 个数均为 i 。
其余的数中,第 j 个数是上一层中第 j−1 个数和第 j 个数的和。小雨想知道这个三角形第 x 层到第 y 层所有数的和,一共有 m 个询问。

输入描述:

第一行两个正整数 n,m,表示这个三角形的层数和询问个数。
接下来 m 行,每行两个正整数 x,y,表示一次询问。

输出描述:

输出共 m 行,每行一个整数,表示一组询问的答案,对 109+7 取模。

示例1

输入

5 3
1 2
1 5
3 5

输出

5
83
78

说明

画出这个三角形:
1
2 2
3 4 3
4 7 7 4
5 11 14 11 5
第 12 层的和为 1+2+2=5
第 15 层的和为 1+2+2+3+4+3+4+7+7+4+5+11+14+11+5=83
第 35 层的和为 3+4+3+4+7+7+4+5+11+14+11+5=78 。

备注:

1n103,1m103,1xyn

神坑题,错了好多次,做题不规范,赛后两行泪,注意,数据可能会溢出,而且要优化算法,减少算法复杂度,防止时间超限和数据溢出导致的wa

数据范围给的很小,可以 O(n2) 暴力构造三角形,预处理出每一行的总和,每个询问把 x∼y 行的和加起来即可(若预处理出第 1∼i 行的和,则可以做到 O(1) 查询)。
更快的做法?每一行的和其实是有规律的,分别为 1,4,10,22,46,94⋯,除了第 11 行的和为 11 外,第 ii行的和为 62i22,那么第 1i (i>1)行的和为

 1+6202+6222+6232++62i22=1+6(2i11)2(i1)=62i12i3 

所以第 xy 行的和就能用前缀和计算了,注意特判 x=1,x=2,y=1 的情况,这样就能够每次 O(log⁡n) 查询。

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <iostream>
 4 #include <string>
 5 #include <math.h>
 6 #include <algorithm>
 7 #include <queue>
 8 using namespace std;
 9 #define maxn 1001
10 long long dp[maxn];
11  
12 int main()
13 {
14     //freopen("sample.txt","r",stdin);
15     int n,m;
16     scanf("%d %d",&n,&m);
17     dp[1]=1;
18     for(int i=2;i<=n;i++)
19     {
20         dp[i]=(dp[i-1]*2+2)%(long long)(pow(10,9)+7);
21     }
22     for(int i=0;i<m;i++)
23     {
24         int a,b;
25         scanf("%d %d",&a,&b);
26         long long sum=0;
27         for(int g=a;g<=b;g++)
28         {
29             sum=(sum+dp[g])%(long long)(pow(10,9)+7);
30         }
31         printf("%lld\n",sum);
32     }
33     return 0;
34 }

 

D-小阳买水果

链接:https://ac.nowcoder.com/acm/contest/949/D
来源:牛客网

题目描述

水果店里有 n个水果排成一列。店长要求顾客只能买一段连续的水果。
小阳对每个水果都有一个喜爱程度 ai,最终的满意度为他买到的水果的喜欢程度之和。
如果和为正(不管是正多少,只要大于 0 即可),他就满意了。
小阳想知道在他满意的条件下最多能买多少个水果。
你能帮帮他吗?

输入描述:

第一行输入一个正整数 n,表示水果总数。
第二行输入 n 个整数 ai,表示小阳对每个水果的喜爱程度。

输出描述:

一行一个整数表示结果。(如果 1 个水果都买不了,请输出 0)

示例1

输入

5
0 0 -7 -6 1

输出

1

备注:

1n2×106,|ai|103

 

想法:i从1到n遍历时,就先求出1到i的和,然后在此sum后,只要有一个sum值比它大,就说明它俩中间的数的和为正数,此时的位置之差就是此刻连续的长度,跟max比较就好了

但数据不允许,要对算法做优化。

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define maxn 2000005
 5 using namespace std;
 6 int sum[maxn],maxx[maxn];
 7 int ans=0;
 8 int main()
 9 {
10     int n;
11     scanf("%d",&n);
12     memset(maxx,-0x3f3f3f,sizeof(maxx));
13     for(int i=1;i<=n;i++)
14     {
15         scanf("%d",&sum[i]);
16         sum[i]+=sum[i-1];
17     }
18     for(int i=n;i>=1;i--)
19     maxx[i]=max(sum[i],maxx[i+1]);
20     for(int l=1,r=1;l<=n&&r<=n;l++,r++)
21     {
22         if(maxx[r]<=sum[l-1]) continue;
23         else while(maxx[r]>sum[l-1]){
24                     r++;
25         }
26         ans=max(ans,r-l);
27      }
28      printf("%d",ans);
29  }

 

 

 

 

 

 1 #include<bits/stdc++.h>
 2 #define rep(X,A,B) for(int X=A;X<=B;X++)
 3 #define tep(X,A,B) for(int X=A;X>=B;X--)
 4 #define LL long long
 5 #define ls son[x][0]
 6 #define rs son[x][1]
 7 const int N=2000010;
 8 const int MOD=1e9+7;
 9 using namespace std;
10  
11 int n;
12  
13 struct nn{
14     int num,pos;
15 }a[N];
16  
17 int cmp(nn A,nn B){
18     if(A.num==B.num)return A.pos>B.pos;
19     return A.num<B.num;
20 }
21  
22 int main(){
23     scanf("%d",&n);
24     int x;
25     rep(i,1,n)scanf("%d",&x),a[i].num=a[i-1].num+x,a[i].pos=i;
26     n++;a[n].pos=a[n].num=0;
27     sort(a+1,a+n+1,cmp);
28     int las=n,ans=0;
29     rep(i,1,n){
30         las=min(las,a[i].pos);
31         if(las<a[i].pos)ans=max(ans,a[i].pos-las);
32     }
33     printf("%d\n",ans);
34     return 0;
35 }

 

 

 

 

题解地址

转载于:https://www.cnblogs.com/jiamian/p/11179585.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值