14:27:40 我习惯在包里藏一瓶百无聊赖,打发人间白云和苍狗设计睡着的未来。 ——《我的名字》焦迈奇
有一种悲伤 叫做期末考试有什么大不了的,你怕什么,它就考什么
期末考的差(划重点,要考),悲伤到连A+Bproblem都打不出来,就只好来写博客!!!
第一题 统计数字
http://219.153.61.2:9000/contest/239/problem/1076
这道题很简单,我用的是sort函数进行排序,然后再输出的。
悲伤到不能打字,话不多说放代码
#include#define ll long long using namespace std; ll n,a[200009]; int main() { scanf("%d",&n); for(ll i=1;i<=n;i++) scanf("%d",&a[i]); sort(a,a+n+1); ll m=a[1],s=1; for(ll i=2;i<=n;i++) { if(a[i]==m)s++; else { cout< " "< endl; m=a[i],s=1; } } cout<" "< endl; return 0; }
14:51:10 江山如此多娇,引无数英雄竞折腰
我太难了!!!
第二题 字符串的展开
http://219.153.61.2:9000/contest/239/problem/1077
题目简单易懂,代码思路简单。就是无限无限无限无限的if条件语句。(唉,成绩杀我)打的我真的是头晕转向。(唉)这道题虽然思路清晰明了,代码也简单,但是有许多许多许多许多细小的问题值得注意一下,要不然一个问题就会挖你10分20分的样子。(唉,期末什么期末,我不要放假,我不要成绩)
- 注意开字符数组,不要看题目说的什么字符串就天真傻傻的去开个字符串,会超出范围,反正字符串跟字符数组差不多的用法。字符数组它不香吗,所以还是建议用字符数组。(专业手抖100年)(唉)!!!
- if语句中的条件要写清楚,比如两边要同为小写或同为数字而且左边比右边小之类的,要理清楚什么时候是<,什么时候是>,什么时候该=。(唉,这点要注意,很重要)
- p1决定字符形式,注意在p1=2时,小写转大写是只有小写才减的!!!数字不要剪,这里要加一个条件,而且再加条件之后要将if语句的位置调换一下(也可以在加条件的基础上再加一个条件),不然又会错一个点。
好了,康康代码吧!!!(唉)
#includenamespace std; char a[1000000]; int p1,p2,p3; int main() { cin>>p1>>p2>>p3; cin>>a; for(int i=0;i
using) { if(a[i]=='-'&&((a[i+1]>='0'&&a[i+1]<='9'&&a[i-1]>='0'&&a[i-1]<='9'&&a[i+1]>a[i-1])||(a[i+1]>='a'&&a[i+1]<='z'&&a[i-1]>='a'&&a[i-1]<='z'&&a[i+1]>a[i-1]))) { char s[1000000]; int o=0; for(int j=a[i-1]+1;j1];j++) { if(p1==3) for(int k=1;k<=p2;k++) s[++o]='*'; else if(p1==1||(j>='0'&&j<='9')) for(int k=1;k<=p2;k++) s[++o]=j; else if(p1==2) for(int k=1;k<=p2;k++) s[++o]=j-32; } if(p3==1) for(int j=1;j<=o;j++) cout<<s[j]; else for(int j=o;j>=1;j--) cout<<s[j]; } else cout<<a[i]; } return 0; }
15:40:44 害!!!
命啊!!!
第三题 矩阵取数游戏
https://www.luogu.com.cn/problem/P1005
这道题不能用简单的暴力做,如果这样做的话,只能得到20分。
这道题实际上是一道dp的题。
其次,因为数据极其的大,所以在比赛是打这道题的时候,只能使用高精度
有一个n×m的矩阵,对于第ii行,每次取走边缘的值Ai,j,增加这一行的得分x,求n行的最大得分总和。因为落实每一行,所以行之间的关系是不大的。
fi,j=max{fi−1,j+Ai−1,j⋅2m−j+i−1,fi,j+1+Ai,j+1⋅2m−j+i−1}
Ans=maxi≤m{fi,i+Ai,i⋅2m}
话不多说,上代码吧
#include#define ll __int128 void print(ll x) { if (x==0) return; if (x)print(x/10); putchar(x%10+'0'); } int n,m; ll ans,a[100],f[100][100],p[100]={1}; ll dp() { memset(f,0,sizeof(f)); for(int i=1;i<=m;i++) for(int j=m;j>=i;j--) f[i][j]=std::max(f[i-1][j]+p[m-j+i-1]*a[i-1],f[i][j+1]+p[m-j+i-1]*a[j+1]); ll maxn=-1; for(int i=1;i<=m;i++) maxn=std::max(maxn,f[i][i]+a[i]*p[m]); return maxn; } int main() { for(int i=1;i<=90;i++) p[i]=p[i-1]<<1; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) scanf("%d",a+j); ans+=dp(); } if(ans==0) puts("0"); else print(ans); return 0; }
以上为懒人算法,考试上是过不去的,好吧。(不要轻易模仿)
以下为我后面那个大佬的高精度代码,感谢大佬给我版权。
#includeusing namespace std; const int N=85,mod=10000; int n,m; int ar[N]; struct node{ int p[505], len; node() { memset(p, 0, sizeof p); len = 0; } void print() { printf("%d", p[len]); for (int i = len - 1; i > 0; i--) { if (p[i] == 0) { printf("0000"); continue; } for (int k = 10; k * p[i] < mod; k *= 10) printf("0"); printf("%d", p[i]); } } }f[N][N],base[N],ans; node operator + (const node &a,const node &b){ node c; c.len = max(a.len, b.len); int x = 0; for (int i = 1; i <= c.len; i++) { c.p[i] = a.p[i] + b.p[i] + x; x = c.p[i] / mod; c.p[i] %= mod; } if (x > 0) c.p[++c.len] = x; return c; } node operator * (const node &a,const int &b){ node c; c.len = a.len; int x = 0; for (int i = 1; i <= c.len; i++) { c.p[i] = a.p[i] * b + x; x = c.p[i] / mod; c.p[i] %= mod; } while (x > 0) c.p[++c.len] = x % mod, x /= mod; return c; } node max(const node &a,const node &b){ if (a.len > b.len) return a; else if (a.len < b.len) return b; for (int i = a.len; i > 0; i--) if (a.p[i] > b.p[i]) return a; else if (a.p[i] < b.p[i]) return b; return a; } inline void basetwo(){ base[0].p[1]=1,base[0].len=1; for(int i=1;i<=m+2;i++){ base[i]=base[i-1]*2; } } inline int read(){ int p=0,f=1; char ch=getchar(); while(!isdigit(ch)) f*=(ch=='-')? -1:1,ch=getchar(); do p=(p<<1)+(p<<3)+(ch^48),ch=getchar(); while(isdigit(ch)); return p*f; } int main(){ n=read(),m=read(); basetwo(); while(n--){ memset(f,0,sizeof f); for(int i=1;i<=m;i++) ar[i]=read(); for(int i=1;i<=m;i++){ for(int j=m;j>=i;j--){ f[i][j] = max(f[i][j], f[i - 1][j] + base[m - j + i - 1] * ar[i - 1]); f[i][j] = max(f[i][j], f[i][j + 1] + base[m - j + i - 1] * ar[j + 1]); } } node Max; for (int i = 1; i <= m; i++) Max = max(Max, f[i][i] + base[m] * ar[i]); ans = ans + Max; } ans.print(); return 0; }
15:19:20 生亦我所欲也,死亦我所欲也(小朋友不要盲目背这句话哦)
暴风哭泣!!!
第四题 树网的核
http://219.153.61.2:9000/contest/239/problem/1079
这道题是关于树的!!!唉,学信奥=洗脑=“树学竞赛”
首先,有几个概念要搞清楚
路径:树网中任何两结点a,b都存在唯一的一条简单路径,用d(a,b)表示以a,b为端点的路径的长度,它是该路径上各边长度之和。我们称d(a, b)为a,b两结点间的距离。
D(v,P)=min{d(v,u)}, u为路径P上的结点。
树网的直径:树网中最长的路径成为树网的直径。对于给定的树网TT,直径不一定是唯一的,但可以证明:各直径的中点(不一定恰好是某个结点,可能在某条边的内部)是唯一的,我们称该点为树网的中心。
偏心距ECC(F):树网T中距路径F最远的结点到路径FF的距离,即
ECC(F)=max{d(v,F),v∈V}
因为树方面的题主要是背模板,所以就直接上代码了。(唉)!!!
#includeusing namespace std; int top,n,s,head[100010],vet[100010],val[100010],nex[100010],a[100010],fa[100010],dis[100010]; bool f[100010]; void add(int u,int v,int c) { nex[++top]=head[u]; head[u]=top; vet[top]=v; val[top]=c; } void dfs(int u,int x) { int e,v; for (e=head[u];v=vet[e],e;e=nex[e]) if (v!=x) { fa[v]=u; dis[v]=dis[u]+val[e]; dfs(v,u); } } void sy(int u,int x,int y) { int e,v; for (e=head[u];v=vet[e],e;e=nex[e]) if (v!=x&&!f[v]) { a[y]=max(a[y],dis[v]-dis[u]); sy(v,u,y); } } int main() { int x,y,z; scanf("%d%d",&n,&s); for (int i=1; i ) { scanf("%d%d%d",&x,&y,&z); add(x,y,z),add(y,x,z); } dfs(1,0); int l=0,r=0; for (int i=1;i<=n;i++) if (dis[i]>dis[l]) l=i; for (int i=1;i<=n;i++) dis[i]=0; dfs(l,0); for(int i=1;i<=n;i++) if(dis[i]>dis[r]) r=i;//两次dfs求直径 fa[l]=0;//注意一定要把根的父亲重置为0,因为在第一次dfs中它是一个结点 for (int i=r;i;i=fa[i]) f[i]=1; for (int i=r;i;i=fa[i]) sy(i,0,i); int ans=0,ss=9999999; for (int i=r;i;i=fa[i]) for (int j=i;j;j=fa[j]) { if(dis[i]-dis[j]>s)break;//优化 ans=max(dis[j],dis[r]-dis[i]);//特殊点 for (int k=i; k!=fa[j]; k=fa[k]) ans=max(ans,a[k]); ss=min(ans,ss); } printf("%d\n",ss); return 0; }