NOIP2002普及组解题报告.docVIP

  • 195
  • 0
  • 约4.52千字
  • 约 4页
  • 2016-12-07 发布于四川
  • 举报
NOIP2002普及组解题报告

NOIp2002普及组解题报告 湖南 黄艺海 题一: 级数求和 [问题描述]: 已知:Sn=1+1/2+1/3+…+1/n。显然对于任意一个整数K,当n足够大的时候,Sn大于K。现给出一个整数K(1=K=15),要求计算出一个最小的n,使得SnK [问题分析]: 这道题目非常简单,题目的意思已经把该题的算法描述得再清楚不过了,初始时Sn=0,n=0,然后每次循环n(n+1,Sn(Sn+1/n,,直到Sn大于K,最后输出K。另外实型(Real是最慢的,建议用Extended)的运算速度不是很快,而K为1~15之间的整数,所以最后可以交一张表(常量数组),以达到最好的效果 [参考程序]: 题二: 选数 [问题描述]: 已知n(1=n=20)个整数x1,x2,…,xn(1=xi=5000000),以及一个整数k(kn)。从n个整数中任选k个整数相加,可分别得到一系列的和。现在,要求你计算出和为素数共有多少种。 [问题分析]: 本题动态规划无从下手,也无数学公式可寻,看来只能搜索(组合的生成算法),其实1=n=20这个约束条件也暗示我们本题搜索是有希望的,组合的生成可用简单的DFS来实现,既搜索这k个整数在原数列中的位置,由于组合不同于排列,与这k个数的排列顺序无关,所以我们可以令a[I]a[I+1](a[I]表示第I个数在原数列中的位置),这个组合生成算法的复杂度大约为C(n,k),下面给出递归搜索算法的框架: Proc Search(dep) Begin for i - a[dep - 1] + 1 to N - (M - dep) do 1:a[dep] - i 2:S - S + x[i] 3:if dep k then Search(dep + 1) else 判断素数 4:S - S - x[i] End 接下来的问题就是判断素数,判断一个整数P(P1)是否为素数最简单的方法就是看是否存在一个素数a(a=sqrt(P))是P的约数,如果不存在,该数就为素数,由于在此题中1=xi=5000000,n=20,所以要判断的数P不会超过100000000,sqrt(p)=10000,因此,为了加快速度,我们可以用筛选法将2…10000之间的素数保存到一个数组里(共1229个),这样速度估计将提高5~6倍。 特别注意:本题是要求使和为素数的情况有多少种,并不是求有多少种素数,比赛时就有很多同学胡乱判重而丢了12分;还有1不是素数,在判素数时要对1做特殊处理。 [参考程序] 题三: 产生数 [问题描述]: 给出一个整数n(n10^30)和k个变换规则(k=15)。 规则: 1个数字可以变换成另一个数字 规则的右部不能为零。 问题: 给出一个整数n和k个规则 求出: 经过任意次的变换(0次或多次),能产生出多少个不同的整数。 [问题分析]: 认真分析题目之后发现,本题搜索显然是不行的,而且对于只需计数而不需求具体方案的题目,一般都不会用搜索解决,其实本题不难看出,可以用乘法原理直接进行计数,用Fi表示数字i包括本身可以变成的数字总个数(这里的变成可以是直接变成也可以是间接变成,比如3-5,5-7,那么3-7),那么对于一个数a(用数组存,长度为n),根据乘法原理它能产生出F[a[1]]*F[a[2]]*F[a[3]]*…F[a[n]]个不同整数,相信这一点大家不难理解。那么现在的关键就是如何求Fi,由于这些变换规则都是反应的数字与数字之间的关系,这很容易让我们想到用图来表示这种关系: 1: 建立一个有向图G,初始化g[i, j] ( False 2: 如果数字i能直接变成数字j,那么g[i, j] ( True 容易知如果数字i能变成数字j,那么i到j必须存在路径,否则i是不可能变成j的,这样一来,Fi的求解就显得非常简单了,求一个顶点v包括本身能到达的顶点数的方法相当多,可以用BFS,DFS,Dijkstra,Floyd,这里介绍一种类似Floyd的有向图的传递闭包算法,该算法实现简单 ,在解决这类问题时比Floyd效率更高,所谓有向图的传递闭包就是指可达性矩阵A=[a[i, j]],其中 a[i, j] = True 从i到j存在通路 a[i, j] = False 从i到j不存在通路 所以有向图传递闭包算法只需将floyd算法中的算术运算符操作‘+’用相应的逻辑运算符‘and’和’or’代替就可以了,其算法如下: for k ( 1 to n do for i ( 1 to n do for j ( 1 to n do a[i, j] =

文档评论(0)

1亿VIP精品文档

相关文档