题目1 : 组队
时间限制:
2000ms
单点时限:
1000ms
内存限制:
256MB
-
1 2 3 3
样例输出
-
Case 1: 9
描述
有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种交换方法都行。
每个组选一个人 用来交换, 使得每个人 最后的排列不在原来的组,求总方案数。
其实 和 每个组的人数没有关系,只是最后结果把每个组的人数乘起来就可以了。
这就是 错排了。 最大数据为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))
这就是 错排了。 最大数据为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],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[n]; ans%=MOD;
printf("Case %d: %lld\n",++time,ans);
}
return 0;
}