Description
在某個夜黑月高的晚上,!!!,原諒我編不下去了。
很美吧?放鬆之後,繼續做題吧。
HS(Handsome)的Ocean在紙上寫下$N$個整數,Ocean把它定義爲$O$序列。
Ocean認爲一個序列的價值的是:序列中不同元素個數。
現在他想知道$O$序列中所有子序列的價值之和。
比如序列$(1, 1, 1)$,共有$7$個子序列,$(1)、(1)、(1)、(1, 1)、(1, 1)、(1, 1)、(1, 1, 1)。$ 價值之和爲$7$。
Input
第一行輸入一個整數$T$,代表有$T$組測試數據。
每組數據佔兩行,第一行輸入一個整數$N$,代表序列元素個數。
接下來一行輸入$N$個整數$a_i$。
注:$1 <= T <= 10000,1 <= N <= 50,1 <= a_i <= 10。$
每組數據佔兩行,第一行輸入一個整數$N$,代表序列元素個數。
接下來一行輸入$N$個整數$a_i$。
注:$1 <= T <= 10000,1 <= N <= 50,1 <= a_i <= 10。$
Output
對每組測試數據,輸出一個結果代表所有子序列價值之和。由於結果會很大,請用$long\,long$(%lld)。
Sample Input
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
Sample Output
7 15 22 7864320
題目鏈接
思路:
我的方案: 組合數+用二進制選數
/*
選數原理
比如 :
num[4]={1,3,5,6}
用四個二進制數表示數組對應位選沒選中
例:1001 表示選中num[0]、num[3]兩個數
*/
#include<cstdio>
#include<cstring>
int num[11];//記錄每個數字出現的次數
long long sum[11];//單個數字的子序列的個數
long long quickm(long long x,long long y)
{
long long ans=1;
while(y>0)
{
if(y&1) ans=ans*x;
y>>=1;
x*=x;
}
return ans;
}
long long solve()
{
long long ans=0;
long long ant,temp;
for(int i=1;i<(1<<10);i++)//選數
{
ant=0;//記錄所選數的個數
temp=1;//記錄中間結果
for(int j=0;j<10;j++)
{
if(i&1<<j)
{
ant++;
temp*=sum[j+1];
}
}
ans+=ant*temp;//價值*方案數
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
memset(sum,0,sizeof(sum));
memset(num,0,sizeof(num));
for(int i=0;i<n;i++)
{
int t;
scanf("%d",&t);
num[t]++;
}
for(int i=1;i<=10;i++)
{
sum[i]=quickm(2,num[i])-1;
}
printf("%lld\n",solve());
}
return 0;
}