1. 程式人生 > 實用技巧 >[CTSC2017] 吉夫特 - Lucas定理,狀態壓縮dp

[CTSC2017] 吉夫特 - Lucas定理,狀態壓縮dp

Description

給定長度為 \(n\)\(a_1,a_2,...,a_n\) 的有多少個長度為 \(\ge 2\) 的不升子序列 \(\{ a_{b_1},a_{b_2},...,a_{b_k} \}\) 滿足 \(\prod_{i=2}^k \binom {a_{b_{i-1}}} {a_{b_i}} \mod 2 > 0\)

Solution

用 Lucas 定理對 \(\binom {a_{b_{i-1}}} {a_{b_i}} \mod 2\) 展開,得知要使合法,必須滿足對於任意的 \(i<j\)\(a_{b_i} \subseteq a_{b_j}\)

。於是暴力 dp,設 \(f[i]\) 表示以值為 \(i\) 的數結尾的符合要求的序列個數,每次新增後更新其所有子集

#include <bits/stdc++.h>
using namespace std;

#define int long long 
const int N = 1000005;
const int mod = 1e9+7;
const int dbg = 1;
int n,x,f[N],ans,tmp;

signed main()
{
    ios::sync_with_stdio(false);

    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>x;
        int s=x,tmp=f[x]+1;
        ans+=tmp-1;
        ans%=mod;
        // 列舉子集
        while(s)
        {
            f[s]+=tmp;
            f[s]%=mod;
            s=s-1&x;
        }
    }
    cout<<ans<<endl;

    if(dbg) system("pause");
}