10.4 竞赛题目选讲

10.4 竞赛题目选讲

10-22 统计问题 (UVA 1640)

给出整数a,b,统计a-b之间的整数(包括a和b),数字0-9分别出现了多少次。

分析:a和b的数据范围到108,直接暴力打表的话好像·······勉强也可以?但是dp打表的时候还需要优化一下,如果直接用f[i][p]表示1-i中数字p的个数,时间不会爆(我特地去UVA看了一下时间限制到了3s),空间······4亿个字节,自己体会一下好了。

于是我们考虑用数位DP,那什么叫做数位DP,我个人理解就是将一个比较大的整数按一位一位进行分割:

用f[len][x][p] 表示长度为len,第一位为x-1,后面全是9的数到1之间数字p的出现次数,例如f[4][3][7] 表示0-2999之间7的出现次数,如果我们需要计算35861-43729中2出现的个数,只需要分别计算0-35681和0-43279中2出现的个数,我们以0-43279为例:

0-43279中2出现的个数=0-39999+40000-42999+43000-43199+43200-43269+43270-43279(2出现的个数)。

像43000-43199即相当于0-199中2的个数,但是对于43200-43269,它前三位还有一个2,也就是说我们在一位一位进行运算时,需要用一个tot来记录递归到某一位之前出现的2的个数,单独计算前面2的出现次数,事实上最多只有500组数据,这么做时间和空间上的复杂度都是很低的。

现在的问题就是怎么打这个表,我们以0-99个0-999中2的个数为例:

于是0-999可以分为0-99,100-199·······十个区间,相加即可。


10-23 多少块土地 (UVA 10213)

有一块椭圆形的地。在边界上选n个点并两两连接得到n(n-1)/2条线段。它们最多能把地分成多少个部分?

分析: 首先我们需要知道一个公式,叫做欧拉公式(好的我知道有很多个欧拉公式,我说的是图论那个):在平面图中,V-E+F=2,其中V为顶点数,E为边(的分段)数,F为面数(事实上为图将平面划分出来的区域数)。

对于我们这道题,需要求将椭圆分成了多少个部分,根据上面的公式我们只需要求V顶点数和E边数,F=E+2-V。

需要注意的是,我们这里将整个椭圆和内部的划分视作了一个完整的图(也就是说,椭圆外的平面也可以被称作一个区域,最终结果需要-1),椭圆上的点为n个。

同时为了让区域最多, 不能有两条以上直线交于一点的情况。也就是说每一个交点对应两条直线, 也就可以用圆周上的4点表示,于是椭圆外的点的个数为C(n,4),图中所有点的个数为:

V=C(n,4)+n

比起点的个数,线段的个数可能难思考一点,除了原本就有的C(n,2)条对角线,每产生一个新的交点会分别在相交的两条线段上增加一条线段,也就是说每有一个交点,线段的数量会增加2,再加上n段圆弧被视作线段,于是图中线段的个数为:

E=2C(n,4)+C(n,2)+n

于是椭圆内被划分的区域数为F-1=E+1-V=C(n,4)+C(n,2)+1(n>=4的情况),n=1,2,3的情况大家就自己单独讨论一下吧。


10-24 ASCII面积 (UVA 1641)

在一个h*w的字符矩阵中用“.”,“、”,“\”和“/”画出一个多边形,计算面积。

分析:看了题目,没明白“、”表示什么(事实上我搜了一下原题发现没有顿号,并且这道题是入门级别的难度),那我们怎么算“/”和“\”围成的面积呢?事实上遍历到“\”和“/”两个符号时并不困难,因为无论如何都要给总面积加上半个方格的面积,这个问题唯一的难点就在于判断“.”在多边形的内部还是多边形的外部。

事实上并不难考虑,从上到下从左到右一个一个字符遍历矩阵,每当我们(抽象意义上)进出一次多边形,我们都需要遍历一个“\”或一个“/”符号,也就是说如果当前遍历过斜杠符号(我们这里统称为斜杠符号)的次数为奇数次,那么代表着进入的次数比出去的次数多一次,遍历到的点符号在多边形内,相反,如果次数为偶数次,代表着进出的次数相等,遍历到的点符号在多边形之外。


10-26 约瑟夫的数论问题 (UVA 1363)

输入正整数n和k,计算Σk mod i (i=1-n)。

分析:首先n和k的数据很大,肯定不能直接做。然而这道题也需要一些储备的数学知识:整数分块及详细证明

事实上并不能完全算是数学方面的知识,更像是数学和计算机结合的一种处理方法。

这个问题让我们求Σk mod i (i=1-n),事实上就相当于求:

在这里插入图片描述

根据前面的整数分块,我们知道可以将后面的式子进行分块进行计算:

在这里插入图片描述

这样子做起来就比较简便了。


10-26 帮帮 Tomisu (UVA 11440)

给定正整数N和M,统计2和N!之间有多少个整数x满足:x的所有素因子都是大于M。输出答案除以108+7的余数。

分析:别想着暴算,因为N和M的值都到了107。那素因子都大于M到底代表什么呢?代表不包含小于等于M的素因子,我们将被小于等于M的素数整除的数筛除出去,得到的即是我们需要的结果。

思路是用筛法将小于等于M的素因子全部筛出来,然后用欧拉函数的方法计算1-N!中不被小于等于M的素因子整除的数的个数即可。


10-27 树林里的树 (UVA 10214)

在满足|x|<=a,|y|<=b的网格中,除了原点之外的整点都种上一棵树。数的半径相较于网格可以忽略不计,但是可以互相遮挡。求从原点处能够看到多少书。设这个值为K,求K/N(N为树的总数)。

分析:坐标轴不用考虑,最多只能看到四棵树,四个象限分别对称于是只用考虑一个象限即可。如果能看到(x,y),代表(x,y)与(0,0)的连线中不被别的树给遮挡住,即 gcd(x,y)=1。

于是问题就很简单了,a<=2000,b<=2000000,于是按照一列一列进行考虑,对于固定的a,在1-b中寻找与a互素的数的个数,只需要将a的素因子计算出,用欧拉函数来处理即可,时间复杂度是非常ok的。


10-28 高速公路 (UVA 1393)

有一个n行m列的点阵,问:一共有多少条非水平非竖直的直线至少穿过其中两个点。

分析:讲个笑话,这道题洛谷上题解都没有。但我想了一个自认为非常美妙的动态规划的做法,用d(i,j)表示n=i,m=j对应的答案,然后我们可以发现这样一个简单的小结论:

在小点阵中满足条件,即非水平非竖直,至少穿过其中两个点的直线,在严格大于小点阵的大点阵中一定满足条件。

于是我们只需要计算新增出来的满足条件的直线即可。我原本是打算一行一行,一列一列进行dp的,结果发现一行一列的点还是太多,那么怎么办呢?我们考虑用容斥定理:

d(i+1,j+1)=d(i+1,j)+d(i,j+1)-d(i,j)(前两个点阵重叠的部分)+穿过点(i+1,j+1)和小点阵中至少一个点的矩阵。

那这个额外产生的直线怎么求呢?大家把整个图旋转,将(i,j)放到(0,0)的位置处,会发现和上面一个问题是一模一样的。


10-29 魔法GCD (UVA 1642)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值