数论小知识(错排、斯特林)

斯特林数:参考维基百科stirling数

第一类Stirling数是有正负的,其绝对值是n个元素的项目分作k个环排列的方法数目。

给定s(n,0) = 0,s(1,1) = 1,有递归关系S(n,k) =S(n − 1,k − 1) + (n-1)S(n − 1,k)

第二类Stirling数n个元素的集定义k个等价类的方法数目。

给定S(n,n) =S(n,1) = 1,有递归关系S(n,k) =S(n − 1,k − 1) +kS(n − 1,k)

第一类stirling数的样题:hdu3625

公式的推导过程:

n个数分成0组有0中排列,一个数分成一组有一种排列。

n个数分成k组,是(一个新数自己一组其余n-1个数分成k-1组  )和 (在n-1个分成k组中插入新数,有n-1种插入方式)

代码:

#include <iostream>
#include <stdio.h>
using namespace std;
long long num[22][22];
long long  fun(int n)//求阶乘
{
	long long ss=1;
	while(n>0) {ss*=n;n--;}
	return ss;
}
int  main()
{
	int t,i,j;
	cin>>t;
	memset(num,0,sizeof(num));//stirling公式
	num[1][1]=1;
	for (i=2;i<21;i++)
	{
		for (j=1;j<=i;j++)
		{
			num[i][j]=num[i-1][j-1]+(i-1)*num[i-1][j];
		}
	}
	while (t--)
	{
		int n,k;
		cin>>n>>k;
		long long rr=0;
		for (i=1;i<=k;i++)
		{
			rr+=num[n][i]-num[n-1][i-1];//减去1自己成环的排列
		}
		double re=(double)rr/fun(n);
		printf("%.4lf\n",re);
	}
	return 0;
}


斯特林公式

求n的阶乘的近似值:

n!=sqrt(2*PI*n)*(PI/e)^n;

位数:len=(int)ceil((N*log(N)-N+log(2*N*PI)/2)/log(10));   //////ceil求上界,即不小于某值的最小整数

错排公式

n各有序的元素应有n!种不同的排列。如若一个排列式的所有的元素都不在原来的位置上,则称这个排列为错排。任给一个n,求出1,2,……,n的错排个数dn共有多少个。

递归关系式为:d(n)=(n-1)(d(n-1)+d(n-2))

d(1)=0,d(2)=1

可以得到:

错排公式为dn=n!(1-1/2!+1/3!-.....+(-1)n/n!)   其中,n!=1*2*3*.....*n,   特别地,有0!=0,1!=1.

斐波那契数列的近似值:

Fn=(1/√5) * [((1+√5)/2)^n-((1-√5)/2)^n](n=1,2,3.....)

两边同时取对数得到:
log10(Fn)=-0.5*log10(5.0)+((double)n)*log(f)/log(10.0)+log10(1-((1-√5)/(1+√5))^n)

其中f=(sqrt(5.0)+1.0)/2.0;
因为log10(1-((1-√5)/(1+√5))^n)趋近于0
所以log10(Fn)=-0.5*log10(5.0)+((double)n)*log(f)/log(10.0);

样题:hdu1568 代码:

#include<iostream>
#include<cmath>
#include<cstdio> 
using namespace std;
const double f = (sqrt(5.0)+1.0)/2;
int main()
{
    int n,i;
    double bit;
    int fac[21] = { 0 , 1 };
    for(i = 2; i < 21; i++) 
        fac[i] = fac[i-1] + fac [i-2];
    while(cin >> n)
    {
        if(n <= 20) {
            cout << fac[n] << endl;
            continue;
        }
        else{
            bit = -0.5*log(5.0)/log(10.0)+((double)n)*log(f)/log(10.0);
            bit = bit - floor(bit); 
            bit = pow(10.0,bit); 
            while(bit < 1000) 
                bit = 10.0 * bit; 
            cout << (int)bit << endl;    
        }
    }
    return 0;
}


你可能感兴趣的:(数论小知识(错排、斯特林))