noip2007提高组题解

Posted mgtnb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了noip2007提高组题解相关的知识,希望对你有一定的参考价值。

认真写博客是不是就不用面对期末成绩了


 

统计数字

https://www.luogu.com.cn/problem/P1097

一眼就想到桶排,但是数据范围太大,数组会爆。

就拍了个序,直接记录输出就完了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 ll a[200004];
 5 int main()
 6 {
 7 //    freopen("count.in","r",stdin);
 8 //    freopen("count.out","w",stdout);
 9     int n;
10     scanf("%d",&n);
11     for(int i=1;i<=n;i++)
12     cin>>a[i];
13     sort(a+1,a+n+1);
14     int t=a[1],num=1;
15     cout<<t<<" ";
16     for(int i=2;i<=n;i++)
17     {
18         if(a[i]==t) num++;
19         else
20         {
21             cout<<num<<endl;
22             num=1;
23             t=a[i];
24             cout<<t<<" "; 
25         }
26     }
27     cout<<num;
28     return 0;
29 } 

 

 


字符串的展开

https://www.luogu.com.cn/problem/P1098

这道题思路清晰,跟着题目直接模拟就可以了。

哇但是这道题太恶心了,考场上直接wa了我6个点,40分的悲伤[勉强微笑]。

然后打了一百多行的代码(我也不知道怎么打出来的),洛谷上过了,学校oj硬是继续wa了一个点。盯着我可爱的小代码一百多行的代码看了好多好多遍,就是找不出来毛病[无可奈何]

然后去找隔壁小姐妹寻求帮助,结果发现大犇代码只有30几行,瞬间觉得自己就是个大蒟蒻。

主要就是注意一下有些数字和字母用‘-’连着的直接输出就行了,然后注意第一个符号是‘-’也直接输出,还有if写多了,不要乱,要逻辑清晰。

大概就这些吧。

代码太长,就贴隔壁小姐妹的吧。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 char a[1000000];
 4 int p1,p2,p3;
 5 int main()
 6 {
 7     cin>>p1>>p2>>p3;
 8     cin>>a;
 9     for(int i=0;i<strlen(a);i++)
10     {
11         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])))
12         {
13             char s[1000000];
14             int o=0;
15             for(int j=a[i-1]+1;j<a[i+1];j++)
16             {
17                 if(p1==3)
18                 for(int k=1;k<=p2;k++)
19                 s[++o]=*;
20                 else if(p1==1||(j>=0&&j<=9))
21                 for(int k=1;k<=p2;k++)
22                 s[++o]=j;
23                 else if(p1==2)
24                 for(int k=1;k<=p2;k++)
25                 s[++o]=j-32;
26                 
27             }
28             if(p3==1)
29             for(int j=1;j<=o;j++)
30             cout<<s[j];
31             else
32             for(int j=o;j>=1;j--)
33             cout<<s[j];
34         }
35         else cout<<a[i];
36     }
37     return 0;
38  } 

 

 


矩阵取数游戏

https://www.luogu.com.cn/problem/P1005

首先还是要推状态转移方程:

f[i][j]=max(f[i-1][j]+a[i-1][j]*2m-j+i-1,f[i][j+1]+a[i][j+1]*2m-j+i-1)


f[i][j]表示当前取数的区间,所以很明显f[i][j]是从f[i-1][j]或f[i][j+1]转移过来的,i正循环,j反循环。

但是,这道题最恶心的点在于开long long 的话会爆,所以要写高精度(好像有什么int 128 的东西,比赛好像不能用,我也手打不来)。

高精度真是个烦人的东西,太麻烦了。。。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int N=85,mod=10000;
  4 int n,m;
  5 int a[N];
  6 struct node
  7 {
  8     int p[505],len;
  9     node() 
 10     {
 11         memset(p,0,sizeof p);
 12         len=0;
 13     }
 14     void print() 
 15     {
 16         printf("%d",p[len]);  
 17         for(int i=len-1;i>0;i--) 
 18         {  
 19             if(p[i]==0) 
 20             {
 21                 printf("0000"); 
 22                 continue;
 23             }
 24             for(int j=10;j*p[i]<mod;j*=10) 
 25             printf("0");
 26             printf("%d",p[i]);
 27         }
 28     }
 29 }f[N][N],base[N],ans;
 30 node operator + (const node &a,const node &b)
 31 {
 32     node c; 
 33     c.len=max(a.len,b.len); 
 34     int x=0;
 35     for (int i=1;i<=c.len;i++) 
 36     {
 37         c.p[i]=a.p[i]+b.p[i]+x;
 38         x=c.p[i]/mod;
 39         c.p[i]%=mod;
 40     }
 41     if(x>0) c.p[++c.len] = x;
 42     return c;
 43 }
 44 node operator * (const node &a,const int &b)
 45 {
 46     node c; 
 47     c.len=a.len; 
 48     int x=0;
 49     for(int i=1;i<=c.len;i++) 
 50     {
 51         c.p[i]=a.p[i]*b+x;
 52         x=c.p[i]/mod;
 53         c.p[i]%=mod;
 54     }
 55     while(x>0)
 56     {
 57         c.p[++c.len]=x%mod;
 58         x/=mod;
 59     } 
 60     return c;
 61 }
 62 node max(const node &a,const node &b)
 63 {
 64     if(a.len>b.len) return a;
 65     else if(a.len<b.len) return b;
 66     for(int i=a.len;i>0;i--)
 67     {
 68         if(a.p[i]>b.p[i]) return a;
 69         else if(a.p[i]<b.p[i])
 70         return b;
 71     }
 72     return a;
 73 }
 74 int main()
 75 {
 76     cin>>n>>m;
 77     base[0].p[1]=1,base[0].len=1;
 78     for(int i=1;i<=m+2;i++)
 79     {
 80         base[i]=base[i-1]*2;
 81     }
 82     while(n--)
 83     {
 84         memset(f,0,sizeof f);
 85         for(int i=1;i<=m;i++) cin>>a[i];
 86         for(int i=1;i<=m;i++)
 87         {
 88             for(int j=m;j>=i;j--)
 89             {
 90                 f[i][j]=max(f[i][j+1]+base[m-j+i-1]*a[j+1],f[i-1][j]+base[m-j+i-1]*a[i-1]); 
 91             }
 92         }
 93         node maxx;
 94         for(int i=1;i<=m;i++)
 95         {
 96             maxx=max(maxx,f[i][i]+base[m]*a[i]);
 97         }
 98         ans=ans+maxx; 
 99     }
100     ans.print();
101     return 0;
102 }

 


树网的核

https://www.luogu.com.cn/problem/P1099

这道题之前机房大佬有讲过,当时有点晕晕乎乎的,后来又自己总结了一些一类的题,大概还是懂了

今天考试的时候用舍弃第三题不检查第二题的时间,边回忆边慢慢地把它打了出来。

思路还是很清晰的。

题目看着复杂,实质上就是求到树的直径上一段不超过s的路径的最远点的最短距离

先两次dfs求出直径,把两端点保存下来。顺便记录每个点的父亲和到根的距离。

然后再新的dfs求出直径上每个点与其他点的最大距离,求最小值。

但是在当前所求路径上还有一些不在该路径上的直径上的点也需要考虑进来。综合求最小值就可以了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,s,tot;
 4 const int N=100005;
 5 int nex[N],head[N],vet[N],val[N];
 6 int fa[N],dis[N],a[N];
 7 bool f[N];
 8 void add(int u,int v,int c) 
 9 { 
10     nex[++tot]=head[u]; 
11     head[u]=tot; 
12     vet[tot]=v; 
13     val[tot]=c; 
14 } 
15 void dfs(int u,int x) 
16 { 
17     int e,v; 
18     for(e=head[u];v=vet[e],e;e=nex[e]) 
19     {
20         if(v!=x) 
21         { 
22             fa[v]=u; 
23             dis[v]=dis[u]+val[e]; 
24             dfs(v,u); 
25         } 
26     }
27 }
28 void st(int u,int x,int y) 
29 { 
30     int e,v; 
31     for(e=head[u];v=vet[e],e;e=nex[e]) 
32     if (v!=x&&!f[v]) 
33     { 
34         a[y]=max(a[y],dis[v]-dis[u]); 
35         st(v,u,y); 
36     } 
37 } 
38 int main()
39 {
40 //    freopen("core.in","r",stdin);
41 //    freopen("core.out","w",stdout);
42     scanf("%d%d",&n,&s);
43     for(int i=1;i<n;i++)
44     {
45         int x,y,z;
46         scanf("%d%d%d",&x,&y,&z);
47         add(x,y,z);
48         add(y,x,z);
49     }
50     dfs(1,0);
51     int l=0,r=0;
52     for(int i=1;i<=n;i++)
53     {
54         if(dis[i]>dis[l]) l=i;
55     }
56     for(int i=1;i<=n;i++) dis[i]=0;
57     dfs(l,0);
58     for(int i=1;i<=n;i++)
59     {
60         if(dis[i]>dis[r]) r=i;
61     }
62     fa[l]=0;
63     for(int i=r;i;i=fa[i]) f[i]=1;
64     for(int i=r;i;i=fa[i])
65     st(i,0,i);
66     int ss=0,ans=99999999;
67     for(int i=r;i;i=fa[i])
68     {
69         for(int j=i;j;j=fa[j])
70         {
71             if(dis[i]-dis[j]>s) break;
72             ss=max(dis[j],dis[r]-dis[i]); 
73             for(int k=i;k!=fa[j];k=fa[k]) 
74             ss=max(ss,a[k]); 
75             ans=min(ans,ss);
76         }
77     }
78     cout<<ans;
79     return 0;
80 }

 

  


待我写完这篇博客,就一头栽进美色学习的海洋畅游。
 

以上是关于noip2007提高组题解的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P1098 [NOIP2007 提高组] 字符串的展开

noip提高组的C语言历届复赛试题

NOIP2007提高组

noip2005提高组 题解

求NOIP2007提高组Pascal语言试题及答案

Noip2007提高组