大闯关的第二章节主要涉及到了数论部分的一些知识以及高精度运算(对于没学过java的咸鱼来讲,虽然磕磕绊绊,修修补补,但还算是过去了)
下面来看看具体涉及到的知识点
1.首当其冲的应该就是gcd和icm的求算,这一部分在我的第二章第一二节都占到了很大的比重。
gcd也就是最大公约数,计算方法常用欧几里得算法,也就是辗转相除法,代码实现如下:
int gcd(int x,int y){
if (min(x,y)==0)return max(x,y);
else return gcd(min(x,y),max(x,y)%min(x,y));
}
icm也就是最小公倍数,计算方法就是两个数的乘积除以最大公约数。
2.然后占较大比重的就是取对数的算法,这个算法适用于高次幂求前几位,或者是求某个大数据有多少位。
具体看完如下解释便一目了然了:
比如典型的,要求N的N次方的首位那个数是多少(N<=1000000000),看似很头疼的问题只需要
令m=N^N,两边同时取对数,由对数的性质,可以得到log10(m)=N*log10(N),便获得了一个在long long 范围以内的数字,
其中m的整数部分表示了这个数有多少位,它的前几位是多少就取决于m的小数部分,令x=pow(10,m),那么,x*10^y取整之后得到的就是
N^N的前y+1位。
3.之后见得比较多的一类题就是卡特兰数和卡特兰数的变式了,这类题大致包括如下题型:
不穿过对角线的路径数
排队买票问题
将多边形分割成数个三角形的问题
火车进站问题
还有很多,具体有多少种问题在数学组合数课件里面有介绍,但是课件对这一部分的介绍并不详细,大部分我是从网上自己学习的,下面
进行简单介绍
卡特兰数的大致推导就是在第一个不符合条件的位置,将之前的状态数进行交换,获得的便是不符合条件的总数
比如,不穿过对角线的路径数,这是一个标准的卡特兰数的问题,假设是一个n*n的图,那么从(0,0)点到(n,n)点的最短路径数总共是C(2n,n)
也就是从2n个方向中选择n个向上走的方向,其他n处自动用向右走填充。现在我们寻找不符合条件的方案总数,也就是穿过对角线的方案总数
假设首次穿过对角线的位置是k,那么将k之前的向右走,向上走的方案总数交换,则一定有n+1个向上走的和n-1个向右走的,换言之,若有n+1步都向上走
那么一定有穿过对角线的时候。于是得到不符合方案的方案总数为C(2n,n+1)。因此,合法的方案数就是C(2n,n)-C(2n,n+1)。
然后就是这类问题的一个变式,就是买票问题,假设售票站没有钱可以找零,要出售一个票价为50元的电影票,现在有n个持有50元的人和m个持有100元的人,
问售票站可以正常售票的排队方案总数。当m=n的时候,这个问题就是标准的卡特兰数,方案数为C(2n,n)-C(2n,n+1),若n<m那么,便有如下推导:
方案总数为C(m+n,n)从第k个持有100元却没法活的找零的购票者开始,之前的持有50元的和100元的人的人数互换,便得到n+1个持有50元的人,因此不合法
的方案总数是C(m+n,n+1)。那么合法的方案总数是C(m+n,n)-c(m+n,n+1)。
当然这样用组合计数推到卡特兰数碰到大数据是没有办法处理的,于是便有公式c(n)=(4*n-2)/(n+1)*c(n-1),这个只适用于标准的卡特兰数的求解。
4.之后再数的上的就是筛素数算法了,这个没什么好说的,就是把素数的倍数筛掉即可,用一个bool类型的数组记录这个数是不是素数。直接贴代码
for (i=2;i<=200000000;i++){
if (b[i]==0)for (j=2*i;j<=2000000000;j+=i){
b[i[=1;
}
}
这样数组b中为0的就是素数。
5.最后一个我用过的知识点就是约瑟夫环了,但是我的那个约瑟夫环和正常的约瑟夫环并不相同,而是一个用暴搜打表的题,这里就不再提了。
介绍就到这里啦,祝大家顺利通关!