Noip2007提高组总结

  两道基础题,后两题比较麻烦,算法想出来后,还是一些细枝末节的问题,需要特别注意,感觉Noip的题目质量还是挺高的,每做一套,都感觉会有大大小小不同的收获,就要月考了,最后把07年的题目总结一下,算是这两天的收获……

T1:统计数字

  没有任何悬念的练习题,排序然后输出……

+ ?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

#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:字符串的展开

  字符串处理的基础题,主要考察读题的仔细程度和编程的素质,尽量代码短一些,那么也好调试一点。

+ ?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

#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分:

+ ?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

#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;

}

  之后粘上高精度的,重载运算符版本……

+ ?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

#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:树网的核

  对于这道题目首先要做到的是找树的直径,可以得出如果有多条直径的话,随便选取一条就可以了,因为越靠近核一定更优,选取链越长一定越优,(未完待续)

时间: 2024-09-30 05:53:46

Noip2007提高组总结的相关文章

NOIP2007 提高组 题解

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

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

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

洛谷 P1097 统计数字(NOIp2007提高组T1)

题目描述 某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*10^9).已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果. 输入输出格式 输入格式: 输入文件count.in包含n+1行: 第一行是整数n,表示自然数的个数: 第2~n+1每行一个自然数. 输出格式: 输出文件count.out包含m行(m为n个自然数中不相同数的个数),按照自然数从小到大的顺序输出.每行输出两个整数,分别是自然数和该数出现的次

Noip2007提高组

目录 t1.统计数字 t2. 2水题 + 1中等 + 1稍难 t1.统计数字 题目 题意:给定n个数,按数字从小到大的顺序输出数字及出现次数. 思路:[水题]爱怎么搞怎么搞,反正我就是要用优先队列. Code: #include <iostream> #include <cstdio> #include <algorithm> #include <queue> using namespace std; //Mystery_Sky // #define INF

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

[NOIP2009] 提高组 洛谷P1073 最优贸易

题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分 为双向通行的道路,双向通行的道路在统计条数时也计为 1 条. C 国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价 格不一定相同.但是,同一种商品在同一个城市的买入价和卖出价始终是相同的. 商人阿龙来到 C 国旅游.当他得知同一种商品在不同城市的价格可能会不同这一信息 之后,便决定在旅游的

洛谷P1063 能量项链 [2006NOIP提高组]

P1063 能量项链 题目描述 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头标记与尾标 记的珠子,这些标记对应着某个正整数.并且,对于相邻的两颗珠子,前一颗珠子的尾标记一定等于后一颗珠子的头标记.因为只有这样,通过吸盘(吸盘是 Mars人吸收能量的一种器官)的作用,这两颗珠子才能聚合成一颗珠子,同时释放出可以被吸盘吸收的能量.如果前一颗能量珠的头标记为m,尾标记为r,后 一颗能量珠的头标记为r,尾标记为n,则聚合后释放的能量为m*r*n(Mar

codevs 1044 拦截导弹 1999年NOIP全国联赛提高组

1044 拦截导弹 1999年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 输入描述 Input Description 输入导弹

3285 转圈游戏 2013年NOIP全国联赛提高组

3285 转圈游戏 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description n 个小伙伴(编号从 0 到 n-1)围坐一圈玩游戏.按照顺时针方向给 n 个位置编号,从0 到 n-1.最初,第 0 号小伙伴在第 0 号位置,第 1 号小伙伴在第 1 号位置,……,依此类推.游戏规则如下:每一轮第 0 号位置上的小伙伴顺时针走到第 m 号位置,第 1 号位置小伙伴走到第 m+1 号位置,……,依此类推