CF gym102586 E. Count Modulo 2【模2下定和選數的方案數】

題目描述:

給出 KK 個互不相同的數 AiA_i,求一個長爲 NN 的序列 {xj},xj[1,K]\{x_j\},x_j\in[1,K],滿足j=1NAxj=S\sum_{j=1}^NA_{x_j}=S 的方案數模2的值。

K200,N,S1018,0Ai105K\le200,N,S\le10^{18},0\le A_i\le10^5

題目分析:

設每個 AiA_i 出現了 pip_i 次,那麼 pi=N,Aipi=S\sum p_i=N,\sum A_ip_i=S,考慮對應到排列上,那麼序列 {p}\{p\} 對方案數的貢獻次數是 N!pi!\frac {N!}{\prod p_i!}

那麼一個序列 {p}\{p\} 的貢獻模2餘1,則要求上面的式子不能被2整除,我們知道式子中含2的因子數 =i=0N2ij=1Kpj2i=\sum_{i=0}^\infty\left\lfloor\frac N{2^i}\right\rfloor-\sum_{j=1}^K\left\lfloor \frac {p_j}{2^i}\right\rfloor

pi=N\sum p_i=N,與庫默爾定理類似,這意味着在二進制下做加法不能進位。即 pip_iNN 二進制下的子集
那麼考慮 NN 每一位 1 分配給哪個 pip_i,即求 i=0[N>>i&1]2iAxi=S\sum_{i=0}^\infty[N>>i\&1]2^iA_{x_i}=S
的序列 {x}[1,K]\{x\}\in[1,K] 的方案數模 2

從低位往高位類數位DP,每次可以確定最低位,設狀態 f[i][V]f[i][V] 爲已經確定了前 ii 位,當前的和爲 2iV2^i*V 的方案數,那麼轉移就是加入一個 AjA_j。然後根據 SS 在當前位的值確定保留哪些方案,然後整體除以2。和最大爲 2MaxA2*MaxA
複雜度 O((K+1)MaxAlogN)O((K+1)*MaxA*\log N),bitset優化至 O(KMaxAwlogN+MaxAlogN)O(K*\frac {MaxA}w\log N+MaxA\log N)

Code:

#include<bits/stdc++.h>
#define LL long long
using namespace std;
int T,K,A[205],Mx;
LL N,S;
bitset<200005>f,g;
int main()
{
	for(scanf("%d",&T);T--;){
		scanf("%lld%lld%d",&N,&S,&K),Mx=0;
		for(int i=1;i<=K;i++) scanf("%d",&A[i]),Mx=max(Mx,A[i]);
		f.reset(),f[0]=1;
		for(int i=0;N;N>>=1,S>>=1,i++){
			if(N&1){
				g.reset();
				for(int j=1;j<=K;j++) g^=f<<A[j];
			}
			else g=f;
			f.reset();
			for(int j=S&1;j<=2*Mx;j+=2) f[j>>1]=g[j];
		}
		printf("%d\n",int(f[S]));
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章