您的位置:首页 > 其它

错排相关

2017-10-11 23:26 543 查看

错排相关

考虑一个有n个元素的排列,若一个排列中所有的元素都不在自己原来的位置上,那么这样的排列就称为原排列的一个错排。n个元素的错排数记为D(n)

公式:D(n)=(n-1)*[D(n-2)+D(n-1)]

特殊地,D(1)= 0, D(2)= 1.

可递推求解.

简化公式:D(n) = [n!/e+0.5] ,其中e是自然对数的底

推导过程:

对于n个元素,一个元素错排数有(n-1)种——放在不同位置的情况有(n-1)种

假设元素a放于元素b的位置,分以下两种情况

1.元素b放于元素a的位置,a与b的位置确定,则剩余(n-2)个元素错排数为D(n-2)

2.元素b放于其他位置,仅能确定a的位置,剩余(n-1)个元素错排数为D(n-1)

根据乘法原理得:D(n)=(n-1)*[D(n-2)+D(n-1)]

http://codevs.cn/problem/1697/⑨要写信

错排+高精度

重载运算符太麻烦了直接写的函数

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
int lena,lenb,lenc,lend,x;
int a[1000010],b[1000010],c[1000010],d[1000010];
void mul(int s)//高精乘
{
memset(d,0,sizeof(d));
int tmp=1;
for(int i=1;i<=lenc;i++)
{
d[tmp]+=s*c[i];
if(d[tmp]>=10)
{
d[tmp+1]+=d[tmp]/10;
d[tmp]%=10;
}
tmp++;
}
lend=tmp;
if(d[lend]==0&&lend>0)
lend--;
}
void add()//高精加
{
lenc=1,x=0;
while(lenc<=lena||lenc<=lenb)
{
c[lenc]=a[lenc]+b[lenc]+x;
x=c[lenc]/10;
c[lenc]%=10;
lenc++;
}
c[lenc]=x;
if(c[lenc]==0&&lenc>0)
lenc--;
}
int main()
{
int n;
scanf("%d",&n);
a[1]=0;
b[1]=1;
lena=lenb=1;
for (int i=3;i<=n;i++)
{
add();
mul(i-1);
for(int i=1;i<=lenb;i++)
a[i]=b[i];
lena=lenb;
for(int i=1;i<=lend;i++)
b[i]=d[i];
lenb=lend;
}
if(n==0)//特判
printf("0");
else if(n==1)
printf("0");
else if(n==2)
printf("1");
else
for(int i=lend;i>=1;i--)
printf("%d",d[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息