Description
给定一个长度为 $n$ 的非负整数序列 $A={a_1,a_2,cdots,a_n}$,对于 $A$ 的一个子序列 $B={a_{b_1},a_{b_2},cdots,a_{b_m}}$($0le mle n$,$1le b_1 < b_2 < cdots < b_mle n$,下同),称 $B$ 是 $A$ 的优秀子序列当且仅当,其任意两个不同元素的按位与结果均为 $0$,即:$forall 1le i < jle m$,满足:$a_{b_i}~mathrm{and}~a_{b_j}=0$,其中 $~mathrm{and}~$ 是按位与运算。
对于子序列 $B={a_{b_1},a_{b_2},cdots,a_{b_m}}$,我们定义其价值为 $varphi(1+sum_{i=1}^m a_{b_i})$,其中 $varphi(x)$ 表示小等于 $x$ 的正整数中与 $x$ 互质的数的个数。
现在请你求出 $A$ 的所有优秀子序列的价值之和,答案对 $10^9+7$ 取模。
Solution
如果将每个数视为$2$的幂次的集合,那么题目就是要求$sum_{x in S}x$,$S$是一个合法序列
因为$2$的幂次相加不会进位,上式就是$cup_{x in S}x$
设$dp_i$表示合法序列中所有元素并为$i$的方案数
那么题中所求即为
$$sum dp_x varphi(x+1)$$
$varphi$可以一次线性筛求出,$dp$可以一次子集DP求出
最后加上空集
#include<iostream> #include<cstdio> #include<cmath> using namespace std; long long n,maxx,tot,m; long long dp[400005]={1},phi[400005],buc[400005],prime[400005],a[1000005],ans=1; bool vst[400005]; const long long mod=1e9+7; inline long long read() { long long f=1,w=0; char ch=0; while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=getchar(); return f*w; } void pre(long long N) { phi[1]=1; for(long long i=2;i<=N;i++) { if(!vst[i]) prime[++tot]=i,phi[i]=i-1; for(long long j=1;j<=tot&&i*prime[j]<=N;j++) { vst[i*prime[j]]=true; if(!(i%prime[j])) { phi[i*prime[j]]=phi[i]*prime[j];break; } else phi[i*prime[j]]=phi[i]*phi[prime[j]]; } } } int main() { n=read(); for(long long i=1;i<=n;i++) a[i]=read(),maxx=max(maxx,a[i]),buc[a[i]]++; while((1<<m)<=maxx) m++; pre(1<<m); for(long long i=1;i<=(1<<m);i++) { for(long long s=i;;s=(s-1)&i) { long long t=i^s; if(s<t) break; (dp[i]+=dp[t]*buc[s]%mod)%=mod; } (ans+=dp[i]*phi[i+1]%mod)%=mod; } for(long long i=1;i<=buc[0];i++) (ans*=2)%=mod; printf("%lld ",ans); return 0; }