noip2015普及组复赛解题报告资料

上传人:w****i 文档编号:97729843 上传时间:2019-09-06 格式:DOC 页数:17 大小:67.50KB
返回 下载 相关 举报
noip2015普及组复赛解题报告资料_第1页
第1页 / 共17页
noip2015普及组复赛解题报告资料_第2页
第2页 / 共17页
noip2015普及组复赛解题报告资料_第3页
第3页 / 共17页
noip2015普及组复赛解题报告资料_第4页
第4页 / 共17页
noip2015普及组复赛解题报告资料_第5页
第5页 / 共17页
点击查看更多>>
资源描述

《noip2015普及组复赛解题报告资料》由会员分享,可在线阅读,更多相关《noip2015普及组复赛解题报告资料(17页珍藏版)》请在金锄头文库上搜索。

1、NOIP2015普及组解题报告南京师范大学附属中学树人学校 CT1. 金币(coin.cpp/c/pas)【问题描述】国王将金币作为工资,发放给忠诚的骑士。第一天,骑士收到一枚金币;之后两天(第二天和第三天),每天收到两枚金币;之后三天(第四、五、六天),每天收到三枚金币;之后四天(第七、八、九、十天),每天收到四枚金币;这种工资发放模式会一直这样延续下去:当连续N天每天收到N枚金币后,骑士会在之后的连续N+1天里,每天收到N+1枚金币。请计算在前K天里,骑士一共获得了多少金币。【输入格式】输入文件名为coin.in。输入文件只有1行,包含一个正整数K,表示发放金币的天数。【输出格式】输出文件

2、名为coin.out。输出文件只有1行,包含一个正整数,即骑士收到的金币数。【数据说明】对于100%的数据,1 K 10,000。【思路】模拟【时空复杂度】O(k),O(1)2、扫雷游戏(mine.cpp/c/pas)【问题描述】扫雷游戏是一款十分经典的单机小游戏。在n行m列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格)。玩家翻开一个非地雷格时,该格将会出现一个数字提示周围格子中有多少个是地雷格。游戏的目标是在不翻出任何地雷格的条件下,找出所有的非地雷格。现在给出n行m列的雷区中的地雷分布,要求计算出每个非地雷格周围的地雷格数。注:一个格子的周围格子包括其上、下

3、、左、右、左上、右上、左下、右下八个方向上与之直接相邻的格子。【输入格式】输入文件名为mine.in。输入文件第一行是用一个空格隔开的两个整数n和m,分别表示雷区的行数和列数。接下来n行,每行m个字符,描述了雷区中的地雷分布情况。字符*表示相应格子是地雷格,字符?表示相应格子是非地雷格。相邻字符之间无分隔符。【输出格式】输出文件名为mine.out。输出文件包含n行,每行m个字符,描述整个雷区。用*表示地雷格,用周围的地雷个数表示非地雷格。相邻字符之间无分隔符。【数据说明】对于100%的数据,1n100,1m100。【思路】模拟【技巧】可将数组多开一圈,省去边界条件的判断。【时空复杂度】O(m

4、n),O(mn)3. 求和(sum.cpp/c/pas)【问题描述】一条狭长的纸带被均匀划分出了n个格子,格子编号从1到n。每个格子上都染了一种颜色colori(用1,m当中的一个整数表示),并且写了一个数字numberi。定义一种特殊的三元组:(x, y, z),其中x,y,z都代表纸带上格子的编号,这里的三元组要求满足以下两个条件:1. x, y, z都是整数,x y z, y x = z y2. colorx=colorz满足上述条件的三元组的分数规定为(x+z)*(numberx+numberz)。整个纸带的分数规定为所有满足条件的三元组的分数的和。这个分数可能会很大,你只要输出整个纸

5、带的分数除以10,007所得的余数即可。【输入格式】输入文件名为sum.in。第一行是用一个空格隔开的两个正整数n和m,n代表纸带上格子的个数,m代表纸带上颜色的种类数。第二行有n个用空格隔开的正整数,第i个数字numberi代表纸带上编号为i的格子上面写的数字。第三行有m个用空格隔开的正整数,第i个数字colori代表纸带上编号为i的格子染的颜色。【输出格式】输出文件名为sum.out。共一行,一个整数,表示所求的纸带分数除以10,007所得的余数。【数据说明】对于第1组至第2组数据,1n100,1m5;对于第3组至第4组数据,1n3000,1m100;对于第5组至第6组数据,1n10000

6、0,1m100000,且不存在出现次数超过20的颜色;对于全部10组数据,1 n 100000, 1 m 100000, 1 colori m, 1 numberi 100000。【思路】先分析一下,我们的任务是什么。题目的要求是求分数和,我们就得把所有符合条件的三元组“找”出来。至少需要枚举三元组(x,y,z)中的一个元素,这里枚举的是z(当然x也可以,不过不要选y,因为y对分数没什么用)。1、因为xyz,所以只需向前枚举x,y2、因为y-x=z-y,所以x+z=2y,x、z同奇偶,且分数与y无关,只需枚举z和x。3、因为colourx=colourz,所以只需枚举z之前同奇偶且同色的x。这

7、样的话时间复杂度是O(n2),能得40分。如何快速枚举x呢?其实不是快速枚举x,是快速枚举分数和。观察三元组分数:(x+z)(numberx+numberz)显然我们不方便处理多项式乘法,那就把它拆开(事实上很多人到这步都放弃了,其实试一试立刻就明白了)=xnumberx+xnumberz+znumberx+znumberz那么对于z的所有合法决策x1,x2,xk根据乘法分配率,分数=(xi*numberxi)+(xi)*numberz +(numberxi) *z+(z*numberz) (1=i=k)由于z是枚举的,所以只需快速得到(xnumberx),x,numberx和k(注意最后一项

8、被算了k次,要乘k)这样我们就可以开4个累加器,分别记录这四个量。而对于不同奇偶性、不同颜色的z有不同的决策x,所以要开一个s2m4的累加器。【时空复杂度】O(n),O(n+m)【注意】题目数据较大,每次计算一定要模10007,否则很容易出错。【样例程序】#include const int maxn=100000;const int maxm=100000;const int p=10007;int n,m,ans;int numbermaxn+1,colourmaxn+1;int s2maxm+14;void init()freopen(sum.in,r,stdin);freopen(su

9、m.out,w,stdout);scanf(%d%d,&n,&m);for(int i=1;i=n;i+)scanf(%d,&numberi);for(int i=1;i=n;i+)scanf(%d,&colouri);void solve()for(int i=1;i=n;i+)int z=i%p,numz=numberi%p,c=colouri,t=i%2;int count=stc0%=p,x=stc1%=p,numx=stc2%=p,x_numx=stc3%=p;ans=(ans+(count*z)%p*numz)%p)%p;ans=(ans+x_numx)%p;ans=(ans+x*

10、numz)%p;ans=(ans+z*numx)%p;stc0+;stc1+=z;stc2+=numz;stc3+=z*numz;void output()printf(%dn,ans);fclose(stdin);fclose(stdout);int main()init();solve();output();return 0;4. 推销员(salesman.cpp/c/pas)【问题描述】阿明是一名推销员,他奉命到螺丝街推销他们公司的产品。螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户。螺丝街一共有N家住户,第i家住户到入口的距离为Si米。由于同一栋房子里可以有多家

11、住户,所以可能有多家住户与入口的距离相等。阿明会从入口进入,依次向螺丝街的X家住户推销产品,然后再原路走出去。阿明每走1米就会积累1点疲劳值,向第i家住户推销产品会积累Ai点疲劳值。阿明是工作狂,他想知道,对于不同的X,在不走多余的路的前提下,他最多可以积累多少点疲劳值。【输入格式】输入文件名为salesman.in。第一行有一个正整数N,表示螺丝街住户的数量。接下来的一行有N个正整数,其中第i个整数Si表示第i家住户到入口的距离。数据保证S1S2Sn108。接下来的一行有N个正整数,其中第i个整数Ai表示向第i户住户推销产品会积累的疲劳值。数据保证Ai103。【输出格式】输出文件名为sale

12、sman.out。输出N行,每行一个正整数,第i行整数表示当X=i时,阿明最多积累的疲劳值。【数据说明】对于20%的数据,1N20;对于40%的数据,1N100;对于60%的数据,1N1000;对于100%的数据,1N100000。【思路】题目要求每一个X的情况,显然不能每个X专门推一遍,要充分利用已知的X的情况,那么很可能会是DP。定义fi为X=i时的最大疲劳值。关键是怎么建立状态转移方程呢?考试时观察了两组样例数据,直觉告诉我fi+1的决策应该会包含fi的决策(此处的决策指住户下标)。事实上也确实如此。证明:设fi的决策为k1,k2,ki(k1 k2 ki),fi+1的决策将fi决策中的k

13、s换成j并增加了一个决策ki+1,fi+1的决策k中最大的为maxk。fi=2*ski+akt(1=t=i)fi+1=2*smaxk+ akt(1=t=s-1)+ akt(s+1=t=i)+aj+aki+12*smaxk+ akt(1=t=s-1)+ akt(s+1=t=i)+aj是X=i时的一种决策的疲劳值(即决策为k1,k2,ks-1,ks+1,ki,kj时)2*smaxk+ akt(1=t=s-1)+ akt(s+1=t=i)+aj=fi2*smaxk+ akt(1=t=s-1)+ akt(s+1=t=i)+aj+ aki+1=fi+ aki+1(即决策为k1,k2,ks,ki,ki+1

14、时的疲劳值)若小于,说明保留ks更优;若等于,对于两个目前疲劳值相等的决策序列k,maxk越小越好(就是说目前走的路程越短越好),因为在maxk左边的决策l只能增加al的疲劳值,而对于maxk右边的决策r则可以增加2*(sr-smaxk)+ar,对于左边,maxk没有影响,而对于右边,maxk越小,后面的f增加疲劳值的空间越大。根据以上原则,虽然决策k1,k2,ks,ki与决策k1,k2,ks-1,ks+1,ki,kj疲劳值相等,但fi选择了前者,说明前者更优。综上,无论小于或等于,决策k1,k2,ks,ki都比决策k1,k2,ks-1,ks+1,ki,kj更优。fi+1的最优决策一定包含了fi的最优决策,证毕.也就是说,对于fi,只需在fi-1的基础上加一个最优决策就可以了。易得出状态转移方程:

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号