考虑没有任何限制的东西,
m个元素分为n个连续的区间,直接用组合数插板法就好了。
考虑如何去掉元素大于$a_i$的限制,
只要给最终的元素个数减掉$a_i$就好了。
考虑如何搞元素个数小于$a_i$的限制,
不妨使用子集反演,要求的是恰好$0$个元素大于$a_i$。
只要钦定其中的每个集合元素大于$a_i$,问题就转化为了容易解决的问题,乘上容斥系数就好了。
因为模数满足$p^k$并不大,使用$exlucas$(实际上就是不断提取$p$这个质因子)就好了。
B. 宇宙序列
因为异或的性质$a\ xor\ b\ xor\ b=a$,题中给出的式子可以转化为异或卷积式。
因为异或卷积具有结合律,可以直接倍增求,使用FWT优化,可以做到$O(pn2^n)$。
通过DFT,可以将异或的卷积式转化为对位相乘。
暴力相加并不容易优化,但是可以发现对位相乘的结果的形式是优美的。
根据异或FWT的DFT性质(可以结合或卷积的子集和理解),可以发现不断在系数/点值两种情况下转换是没有意义的。
只要在点值意义下不断的自乘,累加在另一个数组中就可以了。
设$a$数组DFT之后为$A$数组,那么对于$A_i$,对应的累加结果为$B_i=\sum \limits_{j=0}^{p}A_i^{2^j}$。
问题在于求出$B$,一次性IDFT回去就好了。
利用本题中模数并不大($10007$)的性质,找一下循环节可以做到$O(mod^2)$预处理。
然而正解是一个倍增。
设$f_{x,k}=\sum \limits_{j=0}^{2^k-1}x^{2^j}$
有$f_{x,k}=f_{x,k-1}+f_{x^{2^{2^{k-1}}},k-1}$
询问的时候只要用类似的方法倍增统计就好了。
用一些特殊的技巧,可以将总复杂度做到$O(mod*logp+n*2^n)$。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int mod=10007; 4 const int inv2=5004; 5 const int N=262150; 6 int n,p,d,lim; 7 int a[N],f[mod][32]; 8 inline void fwt(int opt){ 9 for(int i=1;i<lim;i<<=1) 10 for(int j=0;j<lim;j+=i<<1) 11 for(int k=0;k<i;++k){ 12 int x=a[j+k],y=a[j+k+i]; 13 a[j+k]=(x+y)%mod; a[j+k+i]=(x-y+mod)%mod; 14 if(opt==-1) a[j+k]=a[j+k]*inv2%mod,a[j+k+i]=a[j+k+i]*inv2%mod; 15 } 16 } 17 inline int qpow(int x,int k,int mod,int r=1){ 18 for(;k;k>>=1,x=x*x%mod) if(k&1) r=r*x%mod; 19 return r; 20 } 21 inline int query(int x,int k,int ans=0,int r=0){ 22 for(int i=0;i<30;++i) if(k>>i&1) ans+=f[qpow(x,qpow(2,r%5002,mod-1),mod)][i],r+=1<<i; 23 return ans%mod; 24 } 25 inline int read(register int x=0,register char ch=getchar(),register int f=0){ 26 for(;!isdigit(ch);ch=getchar()) f=ch=='-'; 27 for(; isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+(ch^48); 28 return f?-x:x; 29 } 30 int main(){ 31 n=read(); p=read(); d=read(); lim=1<<n; 32 for(int i=0;i<lim;++i) a[i]=read(); 33 for(int i=0;i<mod;++i) f[i][0]=i; 34 for(int i=1;i<30;++i) for(int j=0;j<mod;++j) f[j][i]=(f[j][i-1]+f[qpow(j,qpow(2,(1<<i-1)%5002,mod-1),mod)][i-1])%mod; 35 fwt(1); 36 for(int j=0;j<lim;++j) a[j]=query(a[j],p+1); 37 fwt(-1); 38 printf("%d\n",a[d]); 39 return 0; 40 }