纪中集训2020.01.13【NOIP普及组】模拟赛C组总结————My First Time Write Summary

纪中集训2020.01.13【NOIP普及组】模拟赛C组总结

题目编号 标题
0 【NOIP普及组模拟】取值( numbers.pas/cpp)
1 【NOIP普及组模拟】数对(pairs.pas/cpp )
2 【提高组NOIP2008】传纸条(message.pas/cpp)
3 【提高组NOIP2008】双栈排序 (twostack.pas/c/cpp)

~~巨佬估分:30+100+30+36.4=196.4~
蒟蒻得分:30+10+0+9.1=49.1
崩了!!!
第8,49.1分!!!一共10个人比赛FAQ
在AC代码和WA10分的代码中纠结,幸运的 我自豪的把WA的代码交上去了!
比赛完,巨佬们:啊!我少打了一点,少了个if,忘记附初始值了,差点就AK了!FAQ
蒟蒻(只有我):这个知识点好像还没学,emmmm…

0.【NOIP普及组模拟】取值( numbers.pas/cpp)

题目大意:读入n&m。使得x[1]+x[2]+x[3].......+x[n]=m。使得必须
0<=x[1]<=x[2]<=........x[n]<=m,求(x[1]到x[n])的取法总数 mod 100000007 的值?
样例输入
2
3 2
7 3

样例输出
2
8
 

数据范围限制
对于 10%的数据,1<=n<=m<=10
对于 30%的数据,1<=n<=m<=50
对于 50%的数据,1<=n<=m<=100
对于 100%的数据,T<=20,1<=n<=m<=300
 

分析直接崩了!!!30分,一个递归,看似很水的题目,实际上,还是很水!
正解,巨佬们说不就是个简单附初始值的DP(动态规划)吗?十几分钟就AC了!FAQ实力碾压
正解分析:首先,把对于 100%的数据,T<=20,1<=n<=m<=300,的所有的值都附一个初始值DP式

**f[i,j]:=f[i-1,j]+f[i,j-i];**记得把f[i,0]:=1;
然后直接输出!!!
注意M&N 读入二数的实际意义

附上AC Pascal 代码:

var
        n,x,y:int64;
        i,j,k,sum:longint;
        f:array[-305..305,-305..305]of int64;
begin
        assign(input,'numbers.in');
        reset(input);
        assign(output,'numbers.out');
        rewrite(output);
        readln(n);
        for i:=1 to 305 do
        begin
                f[i,0]:=1;
                for j:=1 to 305 do
                begin
                        f[i,j]:=f[i-1,j]+f[i,j-i];
                end;
        end;
        for i:=1 to n do
        begin
                readln(x,y);
                writeln(f[y,x] mod 100000007);
        end;
        close(input);
        close(output); 
end.

附上AC C++ 代码:

#include<cstdio>
using namespace std;
int t,n,m,k,i,j,f[1001][1001];
int main()
{
	freopen("numbers.in","r",stdin);
	freopen("numbers.out","w",stdout);
	scanf("%d",&t);
	for (k=1;k<=t;k++)
	{
		scanf("%d%d",&m,&n);
		for (i=1;i<=n;i++)
			f[i][0]=1;
		for (i=1;i<=n;i++)
			for (j=1;j<=m;j++)
				f[i][j]=(f[i-1][j]+f[i][j-i])%100000007;
		printf("%d\n",f[n][m]);
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}

1.【NOIP普及组模拟】数对(pairs.pas/cpp )(难(送分) 题)

题目大意:给定一个正整数 n。现在有一个有数对(a, b)组成的序列,其中 1<=a<=n,|b|<=n。
|b|表示 b的绝对值。该序列称为优美的序列,当且仅当以下条件同时满足:
1. 所有的数对都不相同;
2. 对于每一个数对(a,b),a 和|b|不相同。
3. 对于每一个数对(a, b),若 b>0,则它之前一定 存在一个数对(a',b')满足 a'=b 且 b'=0;
4. 对于每一个数对(a, b),若 b<0,则它之前一定 不存在一个数对(a',b')满足 a'=-b 且 b'=0;
5. 对于所有 相邻的数对(a1,b1),(a2,b2),满足 b1 和 b2 不同时为正数且不同时为负数且不同时为 0;
请你求出最长的优美的序列的长度。
例如,当 n=2 时,其中一个最长的优美的序列为(2,-1),(1,0),(1,-2),(2,1),(2,0),(1,2),长度为 6。
输入
仅一行,一个正整数 n。

输出
输出一个整数,如题所述。

样例输入
2

样例输出
6

数据范围限制
对于 20%的数据,n<=4
对于 80%的数据,n<=10^6
对于 100%的数据,n<=10^8

分析:题目天花乱坠,AC 代码!!!***O(1)**;
规律:2
(n-1)2+2=2n2-3n+4;注意特判1
附上AC Pascal 代码:

var
        n:longint;
        ans:extended;
begin
        assign(input,'pairs.in');
        reset(input);
        assign(output,'pairs.out');
        rewrite(output);
        readln(n);
        if n=1 then
        begin
                writeln(n);
                halt;
        end;
        ans:=2*n*n-3*n+4;
        writeln(ans:0:0);
        close(input);
        close(output);
end.

附上AC C++ 代码:

#include<cstdio>
using namespace std;
long long n,ans;
int main()
{
	freopen("pairs.in","r",stdin);
	freopen("pairs.out","w",stdout);
	scanf("%lld",&n);
	if (n==1) 
		ans=1;
	else
		ans=2*n*n-3*n+4;
	printf("%lld",ans);
	fclose(stdin);
	fclose(stdout);
	return 0;
}

2 .【提高组NOIP2008】传纸条(message.pas/cpp)

题目大意: 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题。
一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了。幸运的是,他们可以通过传纸条来进行交流。纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标(1,1),小轩坐在矩阵的右下角,坐标(m,n)。从小渊传到小轩的纸条只可以向下或者向右传递,从小轩传给小渊的纸条只可以向上或者向左传递。

      在活动进行中,小渊希望给小轩传递一张纸条,同时希望小轩给他回复。班里每个同学都可以帮他们传递,但只会帮他们一次,也就是说如果此人在小渊递给小轩纸条的时候帮忙,那么在小轩递给小渊的时候就不会再帮忙。反之亦然。

      还有一件事情需要注意,全班每个同学愿意帮忙的好感度有高有低(注意:小渊和小轩的好心程度没有定义,输入时用0表示),可以用一个0-100的自然数来表示,数越大表示越好心。小渊和小轩希望尽可能找好心程度高的同学来帮忙传纸条,即找到来回两条传递路径,使得这两条路径上同学的好心程度只和最大。现在,请你帮助小渊和小轩找到这样的两条路径。
      输入
    输入文件message.in的第一行有2个用空格隔开的整数m和n,表示班里有m行n列(1<=m,n<=50)。

    接下来的m行是一个m*n的矩阵,矩阵中第i行j列的整数表示坐在第i行j列的学生的好心程度。每行的n个整数之间用空格隔开。

 

输出
输出文件message.out共一行,包含一个整数,表示来回两条路上参与传递纸条的学生的好心程度之和的最大值。

 

样例输入
3 3

0 3 9

2 8 5

5 7 0

样例输出
34

数据范围限制
【限制】

30%的数据满足:1<=m,n<=10

100%的数据满足:1<=m,n<=50


***题目大意复杂 emmm… ***我不但没有因为题目复杂 水就退缩了,反而WA了!!!(10 0分)
记忆化搜索,51000KB,我觉得宽搜会MLE,打了深搜,从(1,1)和(n,m)同时搜。但可能AC 不了,然后正确解法是,四维DP,f[i,j,k,l]表示从左上角到右下角的两个点的位置。考试的时候都想到了可是,没有打出来!!!
巨佬们说不就是个四维DP吗?没什么含金量十几分钟就AC了!WHAT!
冥思苦想了片刻 很久,推了一下!!!原来如此,其实就是四维DP(真的) 重中之重,重点中的重点
30%的数据满足:1<=m,n<=10
100%的数据满足:1<=m,n<=50
你绝对没有发现 50^4不会空间超限哟!
然后在根据方向枚举,两条路径,记得判重,即可!WoW!
这就是我考试居然没打出来的难题 ,水题!神(心)清(态)气(崩)爽(溃)!!!
附上Pascal AC 代码:

uses math;
var
        n,m,i,j,k,l:longint;
        map:array[0..1005,0..1005] of longint;
        f:array[0..55,0..55,0..55,0..55] of longint;
begin
        assign(input,'message.in');
        reset(input);
        assign(output,'message.out');
        rewrite(output);
        readln(n,m);
        for i:=1 to n do
        begin
                for j:=1 to m do
                begin
                        read(map[i,j]);
                end;
                readln;
        end;
        l:=0;
        for i:=1 to n do
        begin
                for j:=1 to m do
                begin
                        for k:=1 to n do
                        begin
                                f[i,j,k,l]:=max(f[i,j,k,l],f[i-1,j,k-1,l]);
                                f[i,j,k,l]:=max(f[i,j,k,l],f[i-1,j,k,l-1]);
                                f[i,j,k,l]:=max(f[i,j,k,l],f[i,j-1,k-1,l]);
                                f[i,j,k,l]:=max(f[i,j,k,l],f[i,j-1,k,l-1]);
                                f[i,j,k,l]:=f[i,j,k,l]+map[i,j];
                                if (i<>k) and (j<>l) then
                                begin
                                        f[i,j,k,l]:=f[i,j,k,l]+map[k,l];
                                end;
                        end;
                end;
        end;
        writeln(f[n,m,n,m]);
        close(input);
        close(output);
end.

附上AC C++ 代码:

#include<cstdio>
#include<cstring>
using namespace std;
int min(int a,int b)
{
    return a<b?a:b;
}
int max(int a,int b)
{
    return a>b?a:b;
}
int main()
{
    freopen("message.in","r",stdin);
    freopen("message.out","w",stdout);
    int n,m;
    int a[51][51];
    int last[51][51];
    bool b[51][51];
    int f[101][51][51];
    memset(f,0,sizeof(f));
    f[2][1][1]=0;
    f[3][1][2]=a[1][2]+a[2][1];
    scanf("%d%d",&m,&n);
    for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++)
            scanf("%d",&a[i][j]);
    for(int i=3;i<=n+m-1;i++)
    {
        for(int j=max(1,i-n);j<=min(m,i-1);j++)
        {
            for(int k=j+1;k<=min(m,i-1);k++)
            {
                if(j==k-1)
                {
                    f[i][j][k]=max(max(f[i-1][j-1][k],f[i-1][j-1][k-1]),f[i-1][j][k])+a[j][i-j]+a[k][i-k];
                }
                else
                {
                    f[i][j][k]=max(max(f[i-1][j-1][k],f[i-1][j-1][k-1]),max(f[i-1][j][k],f[i-1][j][k-1]))+a[j][i-j]+a[k][i-k];
                }
                if(i==n+m-1)
                {
                    printf("%d",f[i][j][k]);
                    return 0;
                }
            }
        }
    }
    return 0;
}

3 【提高组NOIP2008】双栈排序 (twostack.pas/c/cpp)

题目大意:提高组NOIP2008】双栈排序 (twostack.pas/c/cpp) 
(File IO): input:twostack.in output:twostack.out
时间限制: 1000 ms  空间限制: 51000 KB  具体限制  

题目描述
Tom最近在研究一个有趣的排序问题。如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序。

操作a

如果输入序列不为空,将第一个元素压入栈S1

操作b

如果栈S1不为空,将S1栈顶元素弹出至输出序列

操作c

如果输入序列不为空,将第一个元素压入栈S2

操作d

如果栈S2不为空,将S2栈顶元素弹出至输出序列

如果一个1~n的排列P可以通过一系列操作使得输出序列为1,2,…,(n-1),n,Tom就称P是一个“可双栈排序排列”。例如(1,3,2,4)就是一个“可双栈排序序列”,而(2,3,4,1)不是。下图描述了一个将(1,3,2,4)排序的操作序列:

当然,这样的操作序列有可能有几个,对于上例(1,3,2,4),是另外一个可行的操作序列。Tom希望知道其中字典序最小的操作序列是什么。

 

输入
输入文件twostack.in的第一行是一个整数n。

第二行有n个用空格隔开的正整数,构成一个1~n的排列。

 

输出
输出文件twostack.out共一行,如果输入的排列不是“可双栈排序排列”,输出数字0;否则输出字典序最小的操作序列,每两个操作之间用空格隔开,行尾没有空格。

 

样例输入
【输入输出样例1】

4

1 3 2 4



【输入输出样例2】

4

2 3 4 1



【输入输出样例3】

3

2 3 1

 

样例输出
【输入输出样例1】

a b a a b b a b



【输入输出样例2】

0



【输入输出样例3】

a c a b b d



 

数据范围限制
【限制】

30%的数据满足: n<=10

50%的数据满足: n<=50

100%的数据满足: n<=1000


筘表,9.1分(仰天长啸)。不用我说,巨佬们又秒切!

发布了21 篇原创文章 · 获赞 26 · 访问量 7972
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 数字20 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览