【01揹包】B001_AW_異或和是質數的子集數(上限分析+滾動陣列優化記憶體)
阿新 • • 發佈:2020-09-02
給出 n 個互不相同的正整數。
問存在多少個子集,使得子集中所有數的異或和是質數。
由於答案可能很大,請你輸出對 10^9+7 取模後的結果。
輸入格式
第一行包含整數 n。
第二行包含 n 個正整數。
輸出格式
輸出一個整數,表示滿足條件的子集數量對 109+7 取模後的結果。
資料範圍
1≤n≤5000,
1≤ 給定正整數 ≤5000。
輸入樣例:
3
1 2 3
輸出樣例:
4
方法一:dp
子集是無重複元素的,故可看成 01 揹包
- 定義狀態:
- f[i][j] 表示從前 i 個數中選出若干個數,異或和 j 的方案數
- tip:由於異或是不進位的加法,故 n 個數異或的結果不會超過最大數,最大數為 5000,比 \(2^{12}\)
- f[i][j] 表示從前 i 個數中選出若干個數,異或和 j 的方案數
- 思考初始化:
- f[...][...]=0,f[0][0]=1
- 思考狀態轉移方程:
- f[i][j]|=f[i-1][j^A[i]],if (j^A[i] < M)
- 思考輸出:f[n][j],j∈[2,M],if (isPrime(j))
#include<bits/stdc++.h> using namespace std; const int mod=1e9+7, M=pow(2, 13)+5; bool st[M]; void inti() { memset(st, true, sizeof st); for (int i=2; i<M; i++) if (st[i]) for (int j=i*i; j<M; j+=i) st[j]=false; } int main() { std::ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int n; cin>>n; inti(); int A[n+1], f[2][M]; for (int i=1; i<=n; i++) cin>>A[i]; memset(f, 0, sizeof f); f[0][0]=1; int k=1; for (int i=1; i<=n; i++) { for (int j=0; j<M; j++) { f[k][j]=f[k^1][j]; int nx=A[i]^j; if (nx<M) f[k][j]=(f[k][j]+f[k^1][nx])%mod; } k^=1; } int ans=0; for (int j=2; j<M; j++) if (st[j]) ans=(ans+f[k^1][j])%mod; cout << ans; return 0; }