Noip2007提高组总结
两道基础题,后两题比较麻烦,算法想出来后,还是一些细枝末节的问题,需要特别注意,感觉Noip的题目质量还是挺高的,每做一套,都感觉会有大大小小不同的收获,就要月考了,最后把07年的题目总结一下,算是这两天的收获……
T1:统计数字
没有任何悬念的练习题,排序然后输出……
#include <cstdio>
#include <algorithm>
int n,a[200005],pos;
using namespace std;
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%d",&a[i]);
sort(a,a+n); pos=0;
printf("%d ",a[0]);
for(int i=1;i<=n;i++)if(a[i]!=a[i-1]){
printf("%d\n",i-pos),pos=i;
if(a[i])printf("%d ",a[i]);
}
return 0;
}
T2:字符串的展开
字符串处理的基础题,主要考察读题的仔细程度和编程的素质,尽量代码短一些,那么也好调试一点。
#include <cstdio>
#include <cstring>
using namespace std;
#define rep() for(int j=0;j<p2;j++)
char s[1000000];
int p1,p2,p3;
void pr1(int b,int e){for(int i=b;i<=e;i++)rep()printf("%c",(char)i);}
void pr2(int b,int e){for(int i=e;i>=b;i--)rep()printf("%c",(char)i);}
void pr3(int b,int e){for(int i=b;i<=e;i++)rep()printf("%c",'*');}
int main(){
scanf("%d%d%d",&p1,&p2,&p3);
scanf("%s",s); printf("%c",s[0]);
for(int i=1;i<strlen(s);i++){
if(s[i]!='-'){printf("%c",s[i]);continue;}
if(p3==1){
if(s[i-1]>='0'&&s[i+1]<='9'&&s[i-1]<s[i+1]){
if(p1==3)pr3(int(s[i-1])+1,int(s[i+1])-1);
else pr1(int(s[i-1])+1,int(s[i+1])-1); continue;
}
if(s[i-1]>='a'&&s[i+1]<='z'&&s[i-1]<s[i+1]){
if(p1==1)pr1(int(s[i-1])+1,int(s[i+1])-1);
else if(p1==2)pr1(s[i-1]-'a'+'A'+1,s[i+1]-'a'+'A'-1);
else pr3(int(s[i-1])+1,int(s[i+1])-1);
continue;
}
}else{
if(s[i-1]>='0'&&s[i+1]<='9'&&s[i-1]<s[i+1]){
if(p1==3)pr3(int(s[i-1])+1,int(s[i+1])-1);
else pr2(int(s[i-1])+1,int(s[i+1])-1); continue;
}
if(s[i-1]>='a'&&s[i+1]<='z'&&s[i-1]<s[i+1]){
if(p1==1)pr2(int(s[i-1])+1,int(s[i+1])-1);
else if(p1==2)pr2(s[i-1]-'a'+'A'+1,s[i+1]-'a'+'A'-1);
else pr3(int(s[i-1])+1,int(s[i+1])-1);
continue;
}
}printf("%c",s[i]);
}
return 0;
}
T3:矩阵取数游戏
这道题的Dp方程还是比较好推的,就是从中间向两端扩展,然后搜索进去层层外推即可,方程是f[i][j]=max{f[i][j-1]+a[j],f[i+1][j]+a[i]},然后是2的幂次问题,因为直接算幂的话比较慢,所以用霍纳规则,每一次出栈时乘2,就可以了,没打高精度60分:
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long LL;
LL ans,a[81],f[81][81];
LL getans(int s,int t){
if(f[s][t])return f[s][t];
if(s==t)return f[s][s]=2*a[s];
LL t1,t2;
t1=getans(s+1,t)+a[s];
t2=getans(s,t-1)+a[t];
if(t1>t2)return f[s][t]=2*t1;
else return f[s][t]=2*t2;
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
while(n--){
for(int i=1;i<=m;i++)scanf("%d",&a[i]);
memset(f,0,sizeof f);
ans+=getans(1,m);
}
cout<<ans;
return 0;
}
之后粘上高精度的,重载运算符版本……
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef struct bigint{
int le,u[81];
bigint(){le=0;memset(u,0,sizeof(u));}
bigint operator+(const bigint &a){
int l=max(le,a.le);
bigint m;
for(int i=0;i<=l;i++){
m.u[i]+=u[i]+a.u[i];
m.u[i+1]+=m.u[i]/10;
m.u[i]%=10;
}
if(m.u[l+1]!=0)m.le=l+1;
else m.le=l;
return m;
}
bool operator>(const bigint &a){
if(le>a.le)return true;
if(le<a.le)return false;
for(int i=le;i>=0;i--){
if(u[i]>a.u[i])return true;
if(u[i]<a.u[i])return false;
}
return false;
}
friend ostream& operator<<(ostream &cout,bigint a){
for(int i=a.le;i>=0;i--)
cout<<a.u[i];
return cout;
}
friend istream& operator>>(istream &cin,bigint &a){
int i,l;char b[82];
cin>>b;
memset(a.u,0,sizeof(a.u));
a.le=l=strlen(b)-1;
for(int i=0;i<=l;i++)a.u[l-i]=b[i]-'0';
return cin;
}
bool empty(){
if(le==0&&u[0]==0)return true;
else return false;
}
};
bigint a[81],f[81][81];
int n,m;
bigint ans;
bigint getans(int s,int t){
if(!f[s][t].empty())return f[s][t];
if(s==t)return f[s][s]=a[s]+a[s];
bigint t1,t2;
t1=getans(s+1,t)+a[s];
t2=getans(s,t-1)+a[t];
if(t1>t2)return f[s][t]=t1+t1;
else return f[s][t]=t2+t2;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
memset(f,0,sizeof(f));
for(int j=1;j<=m;j++)cin>>a[j];
ans=ans+getans(1,m);
}
cout<<ans;
return 0;
}
T4:树网的核
对于这道题目首先要做到的是找树的直径,可以得出如果有多条直径的话,随便选取一条就可以了,因为越靠近核一定更优,选取链越长一定越优,然后就是实际操作的问题了,一开始因为忘记了pl数组在再次搜索中会被重记而导致WA,特别注意……
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
using namespace std;
int l[305],m,vis[305],head[305],u[605],v[605],w[605],next[605];
bool start;
int tmp,ans,pl[305],now[305],tt,max,pre[305],lis[305],top,ss;
void build(){
memset(head,-1,sizeof(head));
for(int e=1;e<=m;e++){
scanf("%d%d%d",&u[e],&v[e],&w[e]);
u[e+m]=v[e]; v[e+m]=u[e]; w[e+m]=w[e];
next[e]=head[u[e]]; head[u[e]]=e;
next[e+m]=head[u[e+m]]; head[u[e+m]]=e+m;
}
}
void del(int begin,int end){for(int u=begin;u<=end;u++)vis[lis[u]]=1;}
queue Q;
void bfs(int x){
int i,j,k;
vis[x]=1; Q.push(x);
while(!Q.empty()){
int tot=Q.front(); Q.pop();
for(int e=head[tot];~e;e=next[e])if(!vis[v[e]]){
vis[v[e]]=1;
if(start)pre[v[e]]=tot,pl[v[e]]=w[e];
Q.push(v[e]);
l[v[e]]=l[tot]+w[e];
}
}
}
int main(){
int n,x,y,z,k;
start=1;
scanf("%d%d",&n,&k); m=n-1;
build();
bfs(1); int max=0;
for(int i=1;i<=n;i++)if(l[i]>max){max=l[i];tt=i;}
memset(l,0,sizeof l);
memset(vis,0,sizeof vis);
memset(pl,0,sizeof pl);
memset(pre,0,sizeof pre);
bfs(tt); max=0;
start=0;
for(int i=1;i<=n;i++)if(l[i]>max){max=l[i];ss=i;}
int po=ss;
do{lis[top++]=po;po=pre[po];}while(lis[top-1]!=tt);
ans=~0U>>1;
for(int i=0;i<top;i++){
int nl=0,j=i,tmp=0;
while((j+1)<top&&nl+pl[lis[j]]<=k)nl+=pl[lis[j++]];
for(int u=i;u<=j;u++){
max=0;
memset(l,0,sizeof l);
memset(vis,0,sizeof vis);
del(i,j); bfs(lis[u]);
for(int y=1;y<=n;y++)if(l[y]>max)max=l[y];
if(max>tmp)tmp=max;
}
if(tmp<ans)ans=tmp;
}
printf("%d\n",ans);
return 0;
}
注意点:
1.链表开双向边的时候一定要记得开两倍以上的数组;
2.先考虑暴力的情况的,然后再一步步优化,不一定一开始就想标解;
3.在编程时注意初始化,而且对于一些要用的量,一定要注意是否因为后来的操作而改变了,就像T4的错误;
Noip2007提高组总结的更多相关文章
- [NOIP2007] 提高组 洛谷P1098 字符串的展开
题目描述 在初赛普及组的“阅读程序写结果”的问题中,我们曾给出一个字符串展开的例子:如果在输入的字符串中,含有类似于“d-h”或者“4-8”的字串,我们就把它当作一种简写,输出时,用连续递增的字母获数 ...
- luogu1097统计数字[noip2007提高组Day1T1]
题目描述 某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*10^9).已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出 ...
- noip2007提高组题解
题外话:这一年的noip应该是最受大众关心的,以至于在百度上输入noip第三个关键字就是noip2007.主要是由于这篇文章:http://www.zhihu.com/question/2110727 ...
- 洛谷-统计数字-NOIP2007提高组复赛
题目描述 Description 某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*10^9).已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照 ...
- 【NOIP2007提高组】字符串展开
[题外话]这道题纯粹考验耐心,某些经常调程序调到摔键盘的人可以尝试 [题外话2]除了考耐心以外完全没有什么难点 [题外话3]也许会稍微恶心一点? [题外话4]其实我是在别人军训的时候滚来更博客的简直2 ...
- [NOIP2007] 提高组 洛谷P1097 统计数字
题目描述 某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*10^9).已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出 ...
- 洛谷P1098 [NOIP2007 提高组] 字符串的展开
题目链接:https://www.luogu.com.cn/problem/P1098 这个题出的真的很有质量,这个是我见过算是复杂的模拟题了,对付这种题,一丝都不能马虎,要想实现快捷而又简便的代码设 ...
- [NOIp2007提高组]矩阵取数游戏
OJ题号:洛谷1005 思路: 动态规划. 不难发现每行能够取得的最大值仅与当前行的数据有关,因此本题可以对每行的数据分别DP,最后求和. 设$f_{i,j}$表示左边取$i$个.右边取$j$个的最大 ...
- [NOIP2007] 提高组 洛谷P1099 树网的核
题目描述 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边到有正整数的权,我们称T为树网(treebetwork),其中V,E分别表示结点与边的集合,W表示各边长度的集合,并 ...
随机推荐
- C++_知识点_namespace
#include <iostream> #include <string> using namespace std; void name() { cout << & ...
- Log4net 自定义字段到数据库(二)
这种方法比第一种方法麻烦些 Log4Net.config <?xml version="1.0" encoding="utf-8" ?> <c ...
- jaspersoft 5.6.0 相关问题
<property name="net.sf.jasperreports.export.xls.detect.cell.type" value="true" ...
- css如此强大你知道吗
看个这个大神纯 CSS 绘制<辛普森一家>人物头像我惊呆了,css如此牛x <div id="wrap"> <div class="cont ...
- JQ插件开发方法
由于项目原因,不得不写个JQ侧滑插件来满足需求.. 先引用两篇博文,待测试了 再写怎么做.. http://blog.csdn.net/business122/article/details/8278 ...
- 《Pointers On C》读书笔记(第二章 基本概念)
1.从源代码到生成可执行程序的过程整体上可以分为两个阶段:编译和链接.其中,编译过程大致上又可分为:预处理.编译和汇编.预处理阶段主要对源代码中的预处理指令(包含宏定义指令<如 #define& ...
- 设置cmd的codepage的方法
设置cmd的codepage的方法 有时候,我们的cmd.exe的codepage和字体等会变化,比如突然由中文变成英文的codepage(因为一些sh程序的干扰). 下面是修正方法: [HKEY_C ...
- grunt api 文档
Grunt docs Grunt和 Grunt 插件是通过 npm 安装并管理的,npm是 Node.js 的包管理器. 安装 grunt-cli npm install grunt-cli -g 注 ...
- passwordauthentication yes
ssh ip disconnected:no supported authentication methods available(server sent:publickey,gssapi-keyex ...
- 去掉android的屏幕上的title bar
在配置文件里修改 (关键代码:android:theme="@android:style/Theme.NoTitleBar.Fullscreen",如果想只是去除标题栏就后面不用加 ...