【HPU 1011 QAQ的序列组合】

来源:互联网 发布:淘宝窗帘拍摄技巧 编辑:程序博客网 时间:2024/06/16 07:05

1011: QAQ的序列组合
时间限制: 1 Sec 内存限制: 128 MB
提交: 112 解决: 17
[提交][状态][讨论版]
题目描述
QAQ有1−N
共N个不同的整数,已知第i个整数有a[i]
个。
现在QAQ想知道一共有多少种不同的组合方案。
输入
第一行输入一个整数T
,代表有T组测试数据。
每组数据占两行,第一行输入一个整数N,代表N个不同的整数。
接下来输入N个整数a[]。

注:1<=T<=30,1<=N<=10000,0<=a[]<=100

输出

对每组测试数据,输出一个整数代表不同的组合方案。

由于结果可能会很大,请对(109+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种。

记pa[i]是i元素出现的次数。
然后枚举每一个状态,共有(1<<10)−1共1023种状态。
对于状态S而言,若出现N个元素,那么它们的组合方案就是
cnt=(2^(pa[i]−1))∗(2^(pa[i+1]−1))∗…∗(2^(pa[N]−1))。
状态S的贡献就是出现的不同元素和sum 乘上 组合方案cnt。
我们累加贡献即可。
如果爆int,要这样写1 LL << x。
时间复杂度O(T∗1023∗10)。

AC代码 :

#include<cstdio>const long long mod = 1e9 + 7;int pa[10010];long long jc[1000011];long long KSM(long long x,long long y){    long long cut = x % mod;    long long sum = 1;    while(y){        if(y & 1)            sum = sum * cut % mod;        cut = cut * cut % mod;        y /= 2;    }    return sum;}int main(){    int T,N,i,a;    long long ans;    jc[0] = 1;    for(i = 1 ; i <= 1000011 ; i++)        jc[i] = jc[i - 1] * i % mod;    scanf("%d",&T);    while(T--){            ans = 0;        scanf("%d",&N);        for(i = 1 ; i <= N ; i++){            scanf("%d",&pa[i]);            ans += pa[i];        }        if(ans == 0)            printf("0\n");        else{            ans = jc[ans];            for(i = 1 ; i <= N ; i++){                a = pa[i];                if(a)                ans = ans * KSM(jc[a] , mod - 2) % mod;            }        printf("%lld\n",ans);        }    }    return 0;}
0 0
原创粉丝点击