您的位置:首页 > 其它

洛谷 P1595 信封问题

2017-04-20 15:06 316 查看
经典的错位排列问题

题目描述

某人写了n封信和n个信封,如果所有的信都装错了信封。求所有信都装错信封共有多少种不同情况。

输入输出格式

输入格式:

一个信封数n

输出格式:

一个整数,代表有多少种情况。

输入输出样例

输入样例#1:

样例1:2

样例2:3

输出样例#1:

样例1:1

样例2:2

【分析】

容斥原理

ans=至少0个装错的-至少1个装错的+至少2个装错的+…-…+/-至少n个装错的

那么ans=Σ(i:0~n) C
[i]*A[n-i]

C可以用递推关系式得到

C
[k+1]=C
[k]*(n-k)/(k+1)

【代码】

//错位排列
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=100005;
int n,m;
ll c[mxn],fac[mxn],ans;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
int main()
{
int i,j,f=-1;
n=read();
c[0]=fac[0]=1;
fo(i,0,9999) c[i+1]=c[i]*(n-i)/(i+1);
fo(i,1,10000) fac[i]=fac[i-1]*i;
fo(i,0,n)
{
f=-f;
ans+=f*fac[n-i]*c[i];
}
cout<<ans<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: