想了好久才理解了。
容斥+递推,先通过递推,枚举二进制每一位预处理出当小x选该话题时能找到多少个人,再预处理出每个话题容斥情况 。
#include<bits/stdc++.h>
#define mo 1000000007
#define ll long long
using namespace std;
ll m,n,k,f[1100010],g[1100010],x,ans;
ll po(ll x,ll y){ll z=1;while (y){if (y%2==1)z=(x*z)%mo;x=(x*x)%mo;y/=2;}return z;}
int main(){
//freopen("loneliness.in","r",stdin);
//freopen("loneliness.out","w",stdout);
cin>>n;
cin>>n>>m>>k;
for (int i=1;i<=m;i++){scanf("%d",&x);g[x]++;}
f[0]=-1;
for (int i=0;i<(1<<n);i++)
for (int j=1;j<(1<<n);j*=2)
if ((i&j)==0)f[i+j]=f[i]*(-1);//容斥预处理
for (int i=1;i<(1<<n);i*=2)
for (int j=0;j<(1<<n);j++)
if ((i&j)!=0) g[j-i]+=g[j];//递推预处理共同话题人数
for (int i=1;i<(1<<n);i++)ans=(ans+f[i]*po(g[i],k)+mo)%mo;
cout<<ans<<endl;
return 0;
}