G-小石的图形
链接:https://ac.nowcoder.com/acm/contest/949/G
来源:牛客网
题目描述
小石想在一面墙旁边建造一段长度为 n 的篱笆来围出一块地(如图)。
求最大的地的面积。
输入描述:
共一行,输入一个整数 n 。
输出描述:
共一行,输出最大面积,保留 3 位小数。
示例1
输入
1
输出
0.159
备注:
0≤n≤103
一看就是水题,上网搜了下π的取值,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 ",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。
备注:
1≤n≤8,0≤ai,j≤50
刚开始以为很难,后来发现也就是一道水题,从(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个数,分别为 1∼n。两人轮流取数,小石先手。对于每轮取数,都必须选择剩下数中的任意一个数 x,同时还要取走 x,⌊x/2⌋,⌊⌊x/2⌋/2⌋…… 如果某个数不存在,就停止取数(不能一个数都不取)。
谁取走最后一个数,谁就输了。小石想知道自己能否获胜。 如果小石能赢,输出 “Shi”,否则输出 "Yang”(均不输出引号)。
输入描述:
共一行,输入一个数 n。
输出描述:
共一行,输出 "Shi" 或 "Yang"(不输出引号)。
示例1
输入
1
输出
Yang
说明
小石只能取走 1,小阳赢。
示例2
输入
2
输出
Shi
说明
若小石取走 1,则小阳只能取走 2,小石赢。
备注:
1≤n≤109
第一题看到别人几分钟就做出来了,很是懵逼,想不出为什么呀。。。估计可能是规律题,要猜猜
第一次是猜奇数小阳赢,偶数小石赢,错了。
后来发现当 n>1 时先手(小石)总是赢。如何证明:一开始有 1∼n , 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 "); 9 else 10 printf("Shi "); 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 块 。
备注:
1≤n,m≤103,1≤hi≤109,1≤ai<ai+1≤109
我们按海岛的高度 hi 从大到小排序。
假设海岛i在水位为 ai 时被淹没,如果海岛 i−1 和海岛 i+1 都已被淹没,那么就少了一块,答案减 1 。
如果海岛 i−1 和海岛 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 ",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
第 1∼2 层的和为 1+2+2=5 。
第 1∼5 层的和为 1+2+2+3+4+3+4+7+7+4+5+11+14+11+5=83 。
第 3∼5 层的和为 3+4+3+4+7+7+4+5+11+14+11+5=78 。
备注:
1≤n≤103,1≤m≤103,1≤x≤y≤n
神坑题,错了好多次,做题不规范,赛后两行泪,注意,数据可能会溢出,而且要优化算法,减少算法复杂度,防止时间超限和数据溢出导致的wa
数据范围给的很小,可以 O(n2) 暴力构造三角形,预处理出每一行的总和,每个询问把 x∼y 行的和加起来即可(若预处理出第 1∼i 行的和,则可以做到 O(1) 查询)。
1+6⋅20−2+6⋅22−2+6⋅23−2+⋯+6⋅2i−2−2=1+6⋅(2i−1−1)−2⋅(i−1)=6⋅2i−1−2⋅i−3
更快的做法?每一行的和其实是有规律的,分别为 1,4,10,22,46,94⋯⋯,除了第 11 行的和为 11 外,第 ii行的和为 6⋅2i−2−2,那么第 1∼i (i>1)行的和为所以第 x∼y 行的和就能用前缀和计算了,注意特判 x=1,x=2,y=1 的情况,这样就能够每次 O(logn) 查询。
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 ",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
备注:
1≤n≤2×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 ",ans); 34 return 0; 35 }