2017.7.15 C组总结
来源:互联网 发布:码农网java入门 编辑:程序博客网 时间:2024/06/08 18:47
NO.1
题目描述:有n首曲子,每一次播放值最大的音乐,每播完一首音乐,它的值平均分给其他n-1首曲子,如果不能平分,那么多出来的,顺次分给编号靠前的曲子
思路:暴力模拟
每次求出最大值,用两个变量记录它能平分的值和多出来的值
然后循环,枚举1~n,
①如果l<>j就是不为本身,而且v>0还有剩的数
那么,v–,a[j]=a[j]+w+1
②else a[j]+=w
最后,将a[l]=0
代码:
var i,j,n,m,l,w,v:longint; a:array[0..1005] of longint;begin readln(n,m); for i:=1 to n do readln(a[i]); for i:=1 to m do begin l:=0; for j:=1 to n do if a[j]>a[l] then l:=j; writeln(l); w:=a[l] div (n-1); v:=a[l] mod (n-1); for j:=1 to n do begin if (j<>l) and (v>0) then begin dec(v); a[j]:=a[j]+w+1; end else inc(a[j],w); end; a[l]:=0; end;end.
NO.2
题目描述:有n次测量山的高度的值,(一座山定义为高度一开始单调上升(或者不变),然后单调下降(或者不变)),求最宽的山的宽度是多大
思路:前缀和
设l[i]为从i到左连续上升的长度,r[i]为从i到右连续上升的长度
①求l为if h[i]>=h[i-1] then l[i]:=l[i-1]+1,不然l[i]=1
②求l为if r[i]>=h[i+1] then r[i]:=r[i+1]+1,不然r[i]=1
最后枚举i,求ans=max(ans,l[i]+r[i]-1)
代码:
#include <iostream>#include <cstdio>using namespace std;int n,i,a[10001],d[10001],u[10001],ma;int main(){ scanf("%d",&n); for (i=1;i<=n;i++) scanf("%d",&a[i]); for (i=1;i<=n;i++) if (a[i]>=a[i-1]) u[i]=u[i-1]+1; else u[i]=1; for (i=n;i>=1;i--) if (a[i]>=a[i+1]) d[i]=d[i+1]+1; else d[i]=1; for (i=1;i<=n;i++) ma=max(ma,u[i]+d[i]-1); printf("%d",ma);}
NO.3
题目描述:有n分钟,每一分钟可以选择跑d[i]米,耗1点疲劳值或休息一分钟,补一点疲劳值。疲劳值不能大于m,到最后疲劳值必须为0
思路:dp
设f[i][j]为第i分钟疲劳值为j能跑的最大距离
状态转移方程为①当第i分钟跑时,f[i][j]=max(f[i][j],f[i-1][j-1]+d[i])
②因为她如果要休息就必须是疲劳值到0,
那么就有一个前提,就是i>=j,那么f[i][0]=max(f[i][0],f[i-j][j])
f[i][0]=max(f[i][0]+f[i-1][0]),改变答案
代码:
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;int n, m;int f[10010][510], v[10010];int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&v[i]); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { f[i][j]=max(f[i][j],f[i-1][j-1]+v[i]); if(i>=j) f[i][0]=max(f[i][0],f[i-j][j]); } f[i][0]=max(f[i][0],f[i-1][0]); } printf("%d", f[n][0]); return 0;}
NO.4
题目描述:求在一个矩阵中连接两个点,这两个点中间没有点挡住,两个点中间的距离必须为在[l1..l2]的区间中,求有多少种情况
思路:数学+规律
其实这题的本质就是要求矩阵的对角线
首先,可以枚举从(0,0)出发,到任何一个点(i,j)的对角线
那么如果要满足题目的情况,必须gcd(i,j)=0(因为对于任意两个点如果以它们作为左上角和右下角的矩阵的长和宽的最大公因数为1,那么这条对角线上只有两个点【左上角和右下角】),而且这条线的长度在[l1..l2]的区间内(可以用勾股定理)求出
这个点对答案的贡献就是
①如果1<=i<=n,1<=j<=m,那么ans+=(n-i+1)*(m-i+1)*2(因为这个矩阵存在0坐标)
②如果1<=i<=m,1<=j<=n,那么ans+=(n-j+1)*(m-j+1)*2
还要做一波特判,
①如果l1=1,那么就是连接两个相邻的点,ans+=(n+1)*m+(m+1)*n
②如果l1=1,l2>1,那么就是连接长宽为1的矩阵,ans+=n*m*2
代码:
#include<cstdio>#include<iostream>#include<algorithm>using namespace std;unsigned long long ans;int n,m,l1,l2,maxn;bool gcd(int x,int y){ if (x==1) return true; if (y%x==0) return false; return gcd(y%x,x);}int sqr(int x){ return x*x; }int main(){ scanf("%d%d%d%d",&n,&m,&l1,&l2); maxn=max(n,m); ans=0; for (int i=1;i<=maxn-1;i++) for (int j=i+1;j<=maxn;j++) if ((sqr(i)+sqr(j)>=sqr(l1))&&(sqr(i)+sqr(j)<=sqr(l2))) if (gcd(i,j)) { if (i<=n&&j<=m) ans+=(n-i+1)*(m-j+1)*2; if (j<=n&&i<=m) ans+=(n-j+1)*(m-i+1)*2; } if (l1==1) ans=ans+n*(m+1)+m*(n+1); if (l1==1&&l2>1) ans=ans+n*m*2; printf("%lld",ans); return 0;}
- 2017.7.15 C组总结
- 2017.7.6 C组总结
- 2017.7.7 C组总结
- 2017.7.8 C组总结
- 2017.7.9 C组 总结
- 2017.7.11 C组总结
- 2017.7.10 C组总结
- 2017.7.12 C组总结
- 2017.7.13 C组总结
- 2017.7.14 C组总结
- 2016.8.15 C组总结
- 16.8.15 C组总结
- 16.9.15 C组总结
- 16.10.15 C组总结
- 17.4.15C组总结
- 16.7.16 C组总结
- C组7.16题解&总结
- 16.7.17 C组总结
- a 标签中调用js的几种方法
- 常见 HTTP 响应状态码
- 【简记】Java Web 内幕——Servlet介绍,编程
- Java死锁的简单例子
- 【Shell】命令代换
- 2017.7.15 C组总结
- Windows下 搭建WEEX遇到的坑!!
- 156_LETTERS
- 【二分查找】[POJ2366]Sacrament of the sum
- CF Round #424( Div.2) D. Office Keys
- cookie和session的区别
- DOM中NodeList&NamedNodeMap&HTMLCollection简介
- QT GUI界面的使用 opencv选择并显示图片于label中
- 1756_八皇后