链接:https://ac.nowcoder.com/acm/contest/696/D
来源:牛客网
小K有n个雕塑,每个雕塑上有一个整数
若集合T中的每一个元素在n个雕塑上都能找得到,则称这个集合为一个优秀的集合
小K想知道所有大小<=k优秀的集合的价值和是多少
一个优秀的集合的价值可以用F(T)=∏x∈TxF(T)=∏x∈Tx来表示
特别的F(∅)=1, |∅|=0
即求∑ki=0F(T)[|T|==i]∑i=0kF(T)[|T|==i]
输入描述:
两个整数n,k,分别表示雕塑的数量与集合大小的上限 接下来n个整数表示第i个雕塑上的数字aiai是多少
输出描述:
一行表示所有大小<=k优秀集合的权值和
示例1
输入
复制
3 0 1 2 3
输出
复制
1
示例2
输入
复制
3 1 1 2 3
输出
复制
7
示例3
输入
复制
3 2 1 2 3
输出
复制
18
示例4
输入
复制
3 3 1 2 3
输出
复制
24
示例5
输入
复制
8 1 1 6 35 45 65 3 56 8
输出
复制
220
备注:
有10%10%的数据满足k=1
有30%30%的数据满足k=n
以上两个部分包含在100%100%的数据中,但不包含在前30%30%的数据中
对于前30%30%的数据,满足k≤n≤5k≤n≤5
对于100%100%的数据,满足n≤106,1≤ai≤5×103n≤106,1≤ai≤5×103
由于答案可能过大请对109+7取模后输出
题解:因为集合中不能有重复元素所以dp[5009][5009]就够用了,dp[i][j]表示i个
dp[i][j] 代表从集合的前 i 个元素里面选出 j 个元素相乘的结果
/// dp[i][j] = dp[i-1][j-1]*a[i] + dp[i-1][j] 转移方程为 在前i-1个中选出 j 个元素(不含a[i]) 加上在前i-1个元素中选出 j-1个元素,然后把 a[i]加进去
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod=1e9+7;
ll dp[5009][5009];
int vis[5009]={};
int a[5009];
int main()
{
int n,k;
cin>>n>>k;
int ans=0;
int x;
for(int i=1;i<=n;i++)
{
cin>>x;
if(vis[x]==0)
{
a[++ans]=x;
}
vis[x]=1;
}
for(int i=0;i<=5002;i++)
{
dp[i][0]=1;
}
for(int i=1;i<=ans;i++)
{
for(int j=1;j<=i;j++)
{
dp[i][j] = (dp[i-1][j]%mod +dp[i-1][j-1]*a[i]%mod)%mod;
}
}
int y=min(k,ans);
ll sum=0;
for(int i=0;i<=y;i++)
{
sum+=dp[ans][i];
sum%=mod;
}
cout<<sum<<endl;
}