2018/4/12训练日记 随机增量法/斯特林公式/矩阵快速幂
这两天看了一些博客,挑出一些之前没看过的和比较重点的写一下(比如说矩阵快速幂)
随机增量法
用来解决n个点最小圆覆盖的题
随机增量法的定义和证明不在这里解释(我也没看明白)
过程大体是以下流程:
1.将数组重新打乱
2.假设前i个点最小圆覆盖为Ci,检查第i+1个点,若在圆上,则C(i+1)=Ci,继续判
不在:令C(i+1)为第一个点和第i+1个点连线中点,半径为连线长度一半
3.重新检查前i个点是否在圆C(i+1)上。不在的话 令C(i+1)圆心为三角形(i,j,k)外心,并扩增圆C(i+1)半径
例题参考一下 bzoj1336,明天抽时间写一下题解
斯特林公式
斯特林公式(Stirling's approximation)是一条用来取n的阶乘的近似值的数学公式。一般来说,当n很大的时候,n阶乘的计算量十分大,所以斯特林公式十分好用,而且,即使在n很小的时候,斯特林公式的取值已经十分准确。
- n! = ((2*pi*n)^(1/2))*((n/e)^n); 前提是n>3
- //由此可以导出lg(n!) = (lg(2*pi)+lg(n))/2 + n*(lg(n)-lg(e));
主要是用来求n!的位数
将上式取整形再加一就是位数
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
const double e = 2.71828182845;
const double pi = 3.1415926;
int main(void) {
int t, i, f, v;
double a, s;
const double log10_e = log10(e);
const double log10_2_pi = log10(2.0*pi)/2.0;
while (scanf("%d", &t) != EOF && t) {
for (i = 0; i < t; ++i) {
scanf("%d\n", &v);
if (1 == v) {printf("1\n"); continue;}
a = v;
s = log10_2_pi + (a+0.5)*log10(a) - a * log10_e;
f = ceil(s);
printf("%d\n", f); } }
return 0; }
很经典的求法,但之前不了解
矩阵快速幂
其实说矩阵快速幂之前是写过一两篇博客了,今天又看到了几篇博客感觉比较重要,就再写一写回想一下吧
找了一个简单计算矩阵的模板
https://blog.****.net/NYIST_TC_LYQ/article/details/52981353
例题的话 比如说
POJ 3070 题目,让求斐波那契数列,其n更是高达10亿