题目编号 标题
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
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
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
#include
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分(仰天长啸)。不用我说,巨佬们又秒切!