您的位置:首页 > 编程语言

2014 编程之美复赛 题目1 : 组队 (错排)

2014-04-27 13:46 246 查看
本文来自: http://blog.csdn.net/napoleon_acm/article/details/24584311#t1


题目1 : 组队

时间限制:2000ms
单点时限:1000ms
内存限制:256MB


描述

有N支队伍,每个队伍有Ai个选手。
现在,这N支队伍想要进行交流:队伍之间交换选手,使得交换完后,每个队伍有且仅有1人和之前不同。
所以我们想知道,总共存在多少种可行的交换方案。两种交换方案不同,当且仅当,交换后的至少有一支队伍人员的集合不同。


输入

第一行一个整数T (1 ≤ T ≤ 10),表示数据组数。
接下来是T组输入数据,测试数据之间没有空行。
每组数据格式如下:
第一行一个整数N 。第二行N个整数,Ai (1 ≤ Ai≤
100)


输出

对每组数据,先输出“Case x: ”,x表示是第几组数据。然后输出一个整数,表示有多少种可行的交换方案。由于答案可能很大,只需要输出除以109+7之后的余数即可。


数据范围

小数据:1 ≤ N ≤ 10
大数据:1 ≤  N ≤ 100


样例解释

3 * 3种交换方法都行。

样例输入
1
2
3 3


样例输出
Case 1: 9


每个组选一个人 用来交换, 使得每个人 最后的排列不在原来的组,求总方案数。

其实 和 每个组的人数没有关系,只是最后结果把每个组的人数乘起来就可以了。

这就是 错排了。 最大数据为100, 就是如何计算错排 的 方案数了。 

可以这样考虑: 假设有n个人,第一个人可放在(2~n)的任一个组里,共n-1种放法,设第一个人放在了第k个组里,若此时第k个人放在了第1个组里,则只要将剩下的n-2错排,即f(n-2),若第k个人没有放在了第1个组里,可将第1个人的组的位置看成是“第k个组”,即将n-1个人错排,即为f(n-1)

由递推可得,f(n)=(n-1)*(f(n-1)+f(n-2))

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define INF 1000000000
#define MOD 1000000007
typedef long long  LL;
#define N 110
LL dp
,n;
int main()
{
int t,time=0;
dp[1]=0; dp[2]=1;
for(LL i=3;i<=101;i++)
{
dp[i]=(i-1)*(dp[i-1]+dp[i-2]); dp[i]%=MOD;
}
scanf("%d",&t);
while(t--)
{
LL ans=1;
LL tmp;
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&tmp);
ans*=tmp; ans%=MOD;
}
ans*=dp
; ans%=MOD;
printf("Case %d: %lld\n",++time,ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: