专栏文章
P11458 [USACO24DEC] All Pairs Similarity P 题解
P11458题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @miqnfxwd
- 此快照首次捕获于
- 2025/12/04 07:39 3 个月前
- 此快照最后确认于
- 2025/12/04 07:39 3 个月前
取 ,有:
。
我们通过容斥求出 ,后面一项同理。
具体地,我们考虑这样一个错得离谱的算法:
对于每个 ,我们首先对它的所有子集 做 ,然后对 做高维前缀和。最后查询时直接查 。
这个算法错误的原因是,设 ,每个 都对答案有 的贡献,而我们希望总的贡献是 。其实我们只关心集合大小,于是考虑给每个大小为 的集合分配一个系数 ,使之满足我们的期望,即对于每个 ,都有 。
显然 ,而上面的式子可以得出 ,因此可以递推 。
于是我们改为对于每个 ,对它的所有子集 做 ,然后对 做高维前缀和。最后查询时直接查 。
你问怎么“对于每个 ,对它的所有子集 做 ”?可以转成对于 ,用高维后缀和求出有 个 是 的超集,那么 就是 呀!
CPP#include<bits/stdc++.h>
#define ll long long
#define ppc(x) __builtin_popcount(x)
#define rep(x,qwq,qaq) for(int x=(qwq);x<=(qaq);++x)
#define per(x,qwq,qaq) for(int x=(qwq);x>=(qaq);--x)
using namespace std;
#define m107 1000000007
#define maxn 1051000
#define mod m107
template<typename Tp>
int qp(int x,Tp y) {
assert(y>=0);
x%=mod;
int res=1;
while(y) {
if(y&1)res=1ll*res*x%mod;
x=1ll*x*x%mod;
y>>=1;
}
return res;
}
int inv(int x) {
return qp(x,mod-2);
}
struct Combinatorics {
#define Lim 2000000
int fac[Lim+10],invfac[Lim+10];
Combinatorics() {
fac[0]=invfac[0]=1;
rep(i,1,Lim)fac[i]=1ll*fac[i-1]*i%mod;
invfac[Lim]=inv(fac[Lim]);
per(i,Lim-1,1)invfac[i]=1ll*invfac[i+1]*(i+1)%mod;
}
int C(int n,int m) {
if(n<m||n<0||m<0)return 0;
return 1ll*fac[n]*invfac[m]%mod*invfac[n-m]%mod;
}
int A(int n,int m) {
if(n<m||n<0||m<0)return 0;
return 1ll*fac[n]*invfac[n-m]%mod;
}
} comb;
template<int MOD>
struct modint {
int x;
modint() {
x=0;
}
template<typename T>
int norm(T y) {
return (y%MOD+MOD)%MOD;
}
template<typename T>
modint(T y) {
x=norm(y);
}
friend modint operator +(modint a,modint b) {
return a.x+b.x;
}
friend modint operator -(modint a,modint b) {
return a.x-b.x;
}
friend modint operator *(modint a,modint b) {
return 1ll*a.x*b.x;
}
modint& operator +=(modint b) {
return x=norm(x+b.x),*this;
}
modint& operator -=(modint b) {
return x=norm(x-b.x),*this;
}
modint& operator *=(modint b) {
return x=norm(1ll*x*b.x),*this;
}
friend istream& operator >>(istream&is,modint &x) {
ll v;
return is>>v,x.x=norm(v),is;
}
friend ostream& operator <<(ostream&os,modint x) {
return os<<x.x,os;
}
};
using mint=modint<m107>;
int n,k;
int S[maxn],T[maxn];
mint a[maxn],b[maxn];
mint f[maxn],g[maxn];
signed main() {
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>k;
int U=(1<<k)-1;
rep(i,1,n)cin>>S[i];
rep(i,1,n) {
T[i]=U^S[i];
f[T[i]]+=1,g[T[i]]+=ppc(S[i]);
}
rep(i,0,k-1) {
rep(mask,0,U) {
if(~(mask>>i)&1)f[mask]+=f[mask^(1<<i)],g[mask]+=g[mask^(1<<i)];
}
}
a[0]=inv(k);
rep(s,1,k) {
a[s]=inv(k-s);
rep(i,0,s-1)a[s]-=a[i]*comb.C(s,i);
}
rep(mask,0,U)f[mask]*=a[ppc(mask)],g[mask]*=a[ppc(mask)];
rep(i,0,k-1) {
rep(mask,0,U) {
if((mask>>i)&1)f[mask]+=f[mask^(1<<i)],g[mask]+=g[mask^(1<<i)];
}
}
rep(i,1,n)cout<<f[T[i]]*ppc(S[i])+g[T[i]]-n<<'\n';
return 0;
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...