1011: QAQ的序列组合
时间限制: 1 Sec 内存限制: 128 MB提交: 82 解决: 12
[ 提交][ 状态][ 讨论版]
题目描述
QAQ有1 - N共N个不同的整数,已知第i个整数有a[i]个。
现在QAQ想知道一共有多少种不同的组合方案。
现在QAQ想知道一共有多少种不同的组合方案。
输入
第一行输入一个整数T,代表有T组测试数据。
每组数据占两行,第一行输入一个整数N,代表N个不同的整数。
接下来输入N个整数a[]。
注:1 <= T <= 30,1 <= N <= 10000,0 <= a[] <= 100。
每组数据占两行,第一行输入一个整数N,代表N个不同的整数。
接下来输入N个整数a[]。
注:1 <= T <= 30,1 <= N <= 10000,0 <= a[] <= 100。
输出
对每组测试数据,输出一个整数代表不同的组合方案。
由于结果可能会很大,请对(1e9 + 7)取余。
如果所有整数的个数之和为0,我们认为不存在合法的方案。样例输入
2
3
1 1 1
3
1 1 2
样例输出
6
12
提示
对于第二组测试数据,有1 2 3 3共4个整数。
不同组合的方案有:
(1 2 3 3)、(1 3 2 3)、(1 3 3 2)、(2 1 3 3)、(2 3 1 3)、(2 3 3 1)、
(3 1 2 3)、(3 2 1 3)、(3 1 3 2)、(3 2 3 1)、(3 3 1 2)、(3 3 2 1)、
共12种。
来源
<span style="font-size:18px;">#include<cstdio>
#define M 1000000007
#define LL long long
#define maxn 1000000+11
LL num[maxn],pre[maxn];
void Init()
{
num[0]=1;
LL i;
for(i=1;i<maxn;++i)
{
num[i]=num[i-1]*i%M;
}
}
LL quick_pow(LL a,LL n)
{
LL ans=1;
while(n)
{
if(n&1)
{
ans=ans*a%M;
}
a=a*a%M;
n>>=1;
}
return ans;
}
void count()
{
LL i;
for(i=0;i<maxn;++i)
{
pre[i]=quick_pow(num[i],M-2);
}
}
int main()
{
int t;
Init();
count();
scanf("%d",&t);
while(t--)
{
LL up=0,under=1;
int n;
scanf("%d",&n);
while(n--)
{
LL a;
scanf("%lld",&a);
up+=a;
under=under*pre[a]%M;
}
LL ant;
if(up==0)
printf("0\n");
else
{
ant=(num[up]%M*under%M)%M;
printf("%lld\n",ant);
}
}
return 0;
} </span>