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 }

  


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

原文地址:https://www.cnblogs.com/mgtnb/p/12206022.html

时间: 2024-10-09 23:03:31

noip2007提高组题解的相关文章

NOIP2007 提高组 题解

2007 提高组题解 第一题 一开始还想是不是要用哈希表储存呢,但仔细想了一会儿,那个数据量20W 用个快排序,时间是能过的.所以这道题用个STL的快排,再一个循环统计个数就OK了.但最后交上去评测时0分,很尴尬.就是我在数据初始化时从一开始计数,我循环又从一开始,你懂的,多算了一次,爆掉了.改了就100了.200W的话数据就很强了,用哈希好一些. 第二题 额,写得很快,果然这种无脑模拟题最适合我了.但自信没检查,带了3组给的数据就走了.果然错了,过了4个点好像.主要是题没读完,没有判断处于字母

noip2004提高组题解

这次有两道题以前已经做过了,所以分数什么的也没有意义了.发现这年的难度设置极不靠谱,前三题都比较简单,最后一题太难,不知道出题人怎么想的. 第一题:储蓄计划 模拟. 第二题:合并果子 贪心.每次选最小的两堆合并. 第三题:合唱队形 两次动规.题目可以转化为找出一个人,使得以他为尾的最长上升子序列的长度最大,并且以他为首的最长下降子序列的长度也最大. 第四题:虫食算 马上想到搜索.但是规模太大,N可能有26位,如果简单枚举那么运算次数是26!≍4e27:剪枝方面只想到一个很弱的剪枝(对于26的规模

noip2003提高组题解

这一年的前三题虽然难度不高,但是第二题极为繁琐,想在考场上用较短的时间拿到第二题的分数难上加难.所以必须要调整策略,争取拿其他三题的分数.第四题是比较普通的搜索题,分数比较好拿,但是很容易想成树形DP,就只能拿30~50分. ? 第一题:神经网络 模拟 有几个注意点: 输入层(即第一层)的结点的U(阈值)是没有用的: 题目说输出「最后状态非零的输出层神经元状态」,但实际上输出的是状态大于0的值. 由于没有注意到神经元只有在兴奋状态时才会向下传送信号,所以WA了1次. ? 第二题:侦探推理 模拟+

noip2000提高组题解

事实再次向我证明了RP的重要性... 第一题:进制转换 是我最没有把握AC的一道题目却是我唯一一道AC的题目,真是讽刺.看完题目几乎完全没有往正常的解法(取余倒序)去想,直接写了搜索,因为数据范围在2^16,感觉枚举每一位上的数应该就够了,但是在自己的电脑上连样例都用了3.4s,然后想不到任何有效的剪枝,就果断放弃了.最后写完其他三题之后还是回过头看了下这道题,还是没往正常的解法想....结果惊人地AC了...RP真的太重要了. 然后经提醒终于想到了正常一点的解法,查了网上的题解之后开始自己写取

NOIP 2014 提高组 题解

NOIP 2014 提高组 题解 No 1. 生活大爆炸版石头剪刀布 http://www.luogu.org/problem/show?pid=1328 这是道大水题,我都在想怎么会有人错了,没算法,直接模拟,别读错题. 1 int wn[5][5]={{2,0,1,1,0}, 2 {1,2,0,1,0}, 3 {0,1,2,0,1}, 4 {0,0,1,2,1}, 5 {1,1,0,0,2}}; 6 7 int n,na,nb; 8 int a[222],b[222]; 9 int s1,s

noip2010提高组题解

NOIP2010提高组题解 T1:机器翻译 题目大意:顺序输入n个数,有一个队列容量为m,遇到未出现元素入队,求入队次数. AC做法:直接开1000的队列模拟过程. T2:乌龟棋 题目大意:有长度为n的棋盘,每个格子对应一个分数,1,2,3,4的卡片共m张,给出四种卡片各自的数量,求改变出牌顺序能获得的最大分数. 思路:开了一个四维的f[i][j][k][l]来表示每张牌有了几张时的最大分数: F[i][j][k][l]=max(f[i-1][j][k][l],f[i][j-1][k][l],f

noip2009提高组题解

第一题:潜伏者 模拟 注意点: 不同的密文对应的明文不同,反过来,不同的明文对应的密文也不同,我用了两个hash表来实现: 26个明文字母必须有对应的密文字母,我用了两个计数变量来判断是否26个字母都有匹配. ? 第二题:Hankson的趣味题 数论 对 a0, a1, b0, b1 四个数进行质因数分解,然后确定 x 的各质因数的指数的取值范围,运用乘法原理解决.详细分析见下: (引用自http://wenwen.sogou.com/z/q169562042.htm) Gcd(x,a0)=a1

noip2001提高组题解

今天继续感动滚粗.第一次提交170分,不能多说. 第一题:一元三次方程 明明是寒假讲分治的时候做过的题居然还是WA而且只拿了60分,说明知识掌握实在不够牢固. 寒假做的是保留4位小数,原题只保留2位,又因为答案在[-100,100],所以直接枚举-10000到10000即可. 然后鉴于寒假的时候写的二分,我就傻X兮兮地在循环里面写了个二分...尼玛经验害死人啊...更可怕的是题目的hint里也明显地提示了二分...然后我就逗比了. 提交4次AC . 第二题:数的划分 去年学回溯的时候就做过,所以

洛谷 P1098 字符串的展开(NOIp2007提高组T2)

题目描述 在初赛普及组的"阅读程序写结果"的问题中,我们曾给出一个字符串展开的例子:如果在输入的字符串中,含有类似于"d-h"或者"4-8"的字串,我们就把它当作一种简写,输出时,用连续递增的字母或数字串替代其中的减号,即,将上面两个子串分别输出为"defgh"和"45678".在本题中,我们通过增加一些参数的设置,使字符串的展开更为灵活.具体约定如下: (1) 遇到下面的情况需要做字符串的展开:在输入的字