HPU 1192

Welcome To HPU Online Judge!

1192: Sequence [组合数学]

时间限制: 3 Sec 内存限制: 128 MB

提交: 160 解决: 62 

题目描述

在某个夜黑高的晚上,!!!,原谅我编不下去了


很美吧?放松之后,继续做题吧。

HS(Handsome)的Ocean在纸上写下 N

个整数,Ocean把它定义为 O

序列。

Ocean认为一个序列的价值的是:序列中不同元素个数。

现在他想知道 O

序列中所有子序列的价值之和。


比如说:序列 (1,1,2,2) 价值为 2 ,因为序列中有 1 2 两个不同元素。
比如序列 (1,1,1) ,共有 7 个子序列, (1)(1)(1)(1,1)(1,1)(1,1)(1,1,1) 价值之和为 7

输入

第一行输入一个整数 T
,代表有 T 组测试数据。
每组数据占两行,第一行输入一个整数 N ,代表序列元素个数。
接下来一行输入 N 个整数 ai

注: 1<=T<=100001<=N<=501<=ai<=10

输出

对每组测试数据,输出一个结果代表所有子序列价值之和。由于结果会很大,请用 longlong
(%lld)。

样例输入

4
3
1 1 1
4
1 1 1 1
4
10 10 10 8
20
1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10

样例输出

7
15
22
7864320
题意:》》》》

思路:统计每一个数的出现次数,然后用其子集合数乘以选中的个数求和即可(总价值=价值*方案数);

下面附上代码:

/*样例解释 10 10 10 8
10的个数为3,则10所构成的集合数(或者可以理解为方案数)
为2^3-1, 同理
8的方案数为1,那么选数的话共有三种可能(10),(8),(10,8),
其价值分别为10的方案数,8的方案数,10的方案数*8的方案数*2 
求和即可*/ 
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL a[15],sum[15];//a用来记录每个数出现的次数,sum记录每个数的方案数 
int N,T,b;
/*LL Quick_mod(LL a,LL b){//从别的博客上看的算法,可以优化时间和空间复杂度。 
	LL ans=1;
	while(b){
		if(b&1) ans*=a;
		b>>=1;
		a*=a;
	}
	return ans;
}*/
LL solve(){
	LL ans=0;
	for(LL i=1;i<(1<<10);i++){
		LL ams=1;
		LL k=0;
		for(LL j=0;j<10;j++){//选数 
			if(i&(1<<j))
			{
				k++;//记录的选中的数的个数	
				ams*=sum[j+1];//记录其每个数的方案数的和 
			}	
		}
		ans+=ams*k;//总价值=每种可能的方案数*价值的和 
	}
	return ans;
}
int main()
{
	scanf("%d",&T);
	while(T--){
		scanf("%d",&N);
		memset(a,0,sizeof(a));
		memset(sum,0,sizeof(sum));
		while(N--){
			scanf("%d",&b);
			a[b]++;
		}
		for(int i=1;i<=10;i++)
			sum[i]=pow(2,a[i])-1;//计算方案数 
		printf("%lld\n",solve());
	}
	return 0;
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值