杭电 2048 神、上帝以及老天爷(公式法)

题目地址:

  http://acm.hdu.edu.cn/showproblem.php?pid=2048

  话不多说,http://blog.sina.com.cn/s/blog_69fc13c50100lamw.html

概念:  
    全错位排列,n个物质,重新排列顺序,使其均不在原位。
历史:  
    被著名数学家欧拉(Leonhard Euler,1707-1783)称为“组合数论的一个妙题”的“装错信封问题”的两个特例.
  “装错信封问题”是由当时最有名的数学家约翰·伯努利(Johann Bernoulli,1667-1748)的儿子丹尼尔·伯努利(DanidBernoulli,1700-1782)提出来的,大意如下:
  个人写了n封不同的信及相应的n个不同的信封,他把这n封信都装错了信封,问都装错信封的装法有多少种?
公式及证明:
  n个相异的元素排成一排a1,a2,...,an,且ai(i=1,2,...,n)不在第i位的排列数为n!(1-1/1!+1/2!-1/3!+...+(-1)^n*1/n!)
  证明:
  设1,2,...,n的全排列t1,t2,...,tn的集合为I,而使ti=i的全排列的集合记为Ai(1<=i<=n),
  则Dn=|I|-|A1∪A2∪...∪An|.
  所以Dn=n!-|A1∪A2∪...∪An|.
  注意到|Ai|=(n-1)!,|Ai∩Aj|=(n-2)!,...,|A1∩A2∩...∩An|=0!=1.
  由容斥原理:
  Dn=n!-|A1∪A2∪...∪An|=n!-C(n,1)(n-1)!+C(n,2)(n-2)!-C(n,3)(n-3)!+...+(-1)^nC(n,n)*0!

  =n!(1-1/1!+1/2!-1/3!+...+(-1)^n*1/n!

  

  注:理论看的似懂非懂的,但是我记住了公式

 

  

#include <stdio.h>
//装错信封的问题:公式法
double fac(int n)
{
    double s = 1.0;
    int i;
    for( i = 2; i <= n; i++ )
        s = s * i;
    return s;
}

int main()
{
    int c, n, i;
    double s;
    scanf( "%d", &c );
    while( c-- )
    {
        scanf("%d", &n);
        s = 1.0;
        for( i = 1; i <= n; i++ )
            if( i % 2 )
                s = s - 1/fac(i);
            else
                s = s + 1/fac(i);
           printf( "%.2lf%%\n", s*100 );    
    }
    return 0;
}
View Code

 

posted @ 2013-08-02 21:47  翼展zjz  阅读(502)  评论(0编辑  收藏  举报