2016.07.18【初中部 NOIP普及组 】模拟赛题解

来源:互联网 发布:python统计字符串个数 编辑:程序博客网 时间:2024/05/17 01:39

题目链接:http://blog.csdn.net/fengyingjie2/article/details/51945514

总结:在天天刷提高组的日子里(雾,我们渐渐感觉到题目难度的增加。今天老师给我们的普及组,水都要溢出来了!!!差一点就可以AK了!!注意,是一点,没AK。。

         T1:

第一题我看题目,觉得:卧槽,什么b题。然后,我就定义了1个数组,存这个骰(tou)子,前后,上下,左右的数分别是多少,每次累加a[1]即可。这题水到一种境界。虽然我调试了半个小时(手动滑稽),可是还是A了。考验您的:动手能力,实践能力,读题能力,敲键盘能力,一切(无)能(用)力。

<span style="font-size:14px;">var        ans,i,j,n:longint;        s:string;        a,b:array[0..6] of longint;begin        a[1]:=1;        a[2]:=2;        a[3]:=4;        a[4]:=5;        a[5]:=3;        a[6]:=6;        ans:=1;        readln(n);        for i:=1 to n do        begin                readln(s);                if s='North' then                        begin                                b:=a;                                a[1]:=b[2];                                a[2]:=b[6];                                a[6]:=b[4];                                a[4]:=b[1];                        end;                if s='East' then                        begin                                b:=a;                                a[1]:=b[3];                                a[3]:=b[6];                                a[6]:=b[5];                                a[5]:=b[1];                        end;                if s='West' then                        begin                                b:=a;                                a[1]:=b[5];                                a[5]:=b[6];                                a[6]:=b[3];                                a[3]:=b[1];                        end;                if s='South' then                        begin                                b:=a;                                a[1]:=b[4];                                a[4]:=b[6];                                a[6]:=b[2];                                a[2]:=b[1];                        end;                if s='Right' then                        begin                                b:=a;                                a[2]:=b[5];                                a[5]:=b[4];                                a[4]:=b[3];                                a[3]:=b[2];                        end;                if s='Left' then                        begin                                b:=a;                                a[2]:=b[3];                                a[3]:=b[4];                                a[4]:=b[5];                                a[5]:=b[2];                        end;                inc(ans,a[1]);        end;        writeln(ans);end.</span>
T2:

这道题我拿到手里,心想满满的200分!!可是看了下数据范围,心碎了。因为做多了提高组,我还想了N多种约数和的算法(一切皆浮云)。其实很水,就只要记录一下出现过的数的约数和,没出现过做一下,记录。辛亏考试发现一个错误,否则白白丢了50分。

<span style="font-size:14px;">var        n,i,j,k,ans:longint;        a:array[0..5000000] of longint;begin        readln(n);        for i:=1 to n do        begin                readln(k);                if a[k]=0 then                begin                        ans:=0;                        for j:=1 to trunc(sqrt(k)) do                                if k mod j=0 then inc(ans,j+k div j);                        if trunc(sqrt(k))=sqrt(k) then dec(ans,trunc(sqrt(k)));//求约数和,如果平方的话,因数同,则减其一。                        a[k]:=ans;//记录                end;                writeln(a[k]);        end;end.</span>

T3:

第三道题其实就是一个水递归,求住酒店有多少种不同的方法,没那么难理解。如果当前酒店位置+x~y之间没有酒店,则到达不了7000,结果为0。递归一下当前位置可以到达的酒店即可。同学说DP,还推出了一个神奇的DP动态转移方程,2、用dp。枚举i(1<=i<=n)和j(1<=j<i)如果(a[ i ] - a[ j ]>=A) and (a[ i ] - a[ j ]<=B),那么f[ i ]:=f[ i ]+f[ j ];牛逼!不过好像我的效率比他还快。

<span style="font-size:14px;">var        a,b:array[0..20000] of longint;        n,i,j,x,y,k,ans:longint;        bz:boolean;procedure dg(num:longint);var        i:longint;begin        if num=7000 then                inc(ans);        if num>7000 then exit;        for i:=x to y do                if (b[num+i]=0)and(a[num+i]=1) then//递归当前范围内可以到达的酒店                begin                        b[num+i]:=1;//记录到达过木有                        dg(num+i);                        b[num+i]:=0;                end;end;begin        readln(x);        readln(y);        readln(n);        for i:=1 to n do        begin                readln(k);                a[k]:=1;        end;        a[990]:=1;a[1010]:=1;a[1970]:=1;a[2030]:=1;a[2940]:=1;a[3060]:=1;        a[3930]:=1;a[4060]:=1;a[4970]:=1;a[5030]:=1;a[5990]:=1;a[6010]:=1;a[7000]:=1;//提前赋值,原谅我的智商        bz:=false;        for i:=x to y do                if a[i]=1 then                begin                        bz:=true;                        break;                end;//不能到达,就输出0了。        if not bz then        begin                writeln(0);                halt;        end;        dg(0);        writeln(ans);end.//水水的AC,水水更健康嘛~</span>
T4:

这道题,我比赛打了个全排列+n²的枚举,结果差点爆0.本想着找规律,但是没有勇气,否则就可能AK啦..其实列出来(用递归暴力列出来,一定要!),就可以发现前所未有的规律,有2个规律,一个是m<n的,一个是m>=n的,分别想想这两个规律,外加一个中间重复的即可。一般聪明的人就像我(雾,就可以发现是一个回文串233333. if j<i then f[i,j]:=f[i-1,j]+f[i,j-1];if j>=i then f[i,j]:=f[i-1,j]+f[i,j-1]-f[i-1,j-i];记得要mod 10000,为避免负数,可以加一个不影响结果的10000。这道题有更水的方法,顺便也贴一个代码。我的:原谅代码丑

<span style="font-size:14px;">var        i,j,n,m,t,ans:longint;        f:array[0..100,0..4950] of longint;begin        readln(n,m);        f[1,0]:=1;        f[2,0]:=1;f[2,1]:=1;//提前赋值        for i:=3 to n do        begin                t:=(i-1)*i div 2;                if odd(t) then//中间相等的情况                begin                        f[i,0]:=1;                        for j:=1 to i-1 do                                f[i,j]:=(f[i-1,j]+f[i,j-1]+10000) mod 10000;                        ans:=0;                        for j:=i to t div 2 do                        begin                                f[i,j]:=(f[i-1,j]+f[i,j-1]-f[i-1,ans]+10000) mod 10000;                                inc(ans);                        end;                        f[i,t div 2+1]:=f[i,t div 2];                        for j:=0 to t div 2-1 do                                f[i,j+t div 2+2]:=(f[i,t div 2-j-1]+10000) mod 10000;                end                else                begin                        f[i,0]:=1;                        for j:=1 to i-1 do                                f[i,j]:=(f[i-1,j]+f[i,j-1]+10000) mod 10000;                        ans:=0;                        for j:=i to (i-1)*i div 2 do                        begin                                f[i,j]:=(f[i-1,j]+f[i,j-1]-f[i-1,ans]+10000) mod 10000;                                inc(ans);                        end;//不用说了,都是水                end;        end;        writeln(f[n,m]);end.</span>
老师的:
<span style="font-size:14px;">var  f,g:array[-10000..10000]of integer;  n,t,j,i:longint;begin  readln(n,t);  fillchar(f,sizeof(f),0);  f[0]:=1;  for i:=2 to n do    begin      for j:=0 to i*(i-1)shr 1 do        g[j]:=(g[j-1]-f[j-i]+f[j])mod 10000;      for j:=0 to i*(i-1)shr 1 do        f[j]:=g[j];    end;  writeln((f[t]+10000)mod 10000);end.</span>

0 0
原创粉丝点击