[CTSC2017]吉夫特

一道不难但是拖了很久的题,我这个傻逼活该要退役.

Click here to read the problem.

N=log2(maxai) N = l o g 2 ( m a x a i ) .
网上很多 3N 3 N 的做法,不具体说了,大概就是 dp[x] d p [ x ] 代表以 x x 结尾的方案数.

考虑分块,把数字二进制下分成前一段和后一段.
f[u][v]=vxdp[u2N2+x] f [ u ] [ v ] = ∑ v ∈ x ∗ d p [ u ∗ 2 N 2 + x ] .即前一半为 u u ,后一半 v v 的超集的方案数之和.(超集就是子集的补集).

每加进一个数字,枚举前一半的超集,计算答案;再枚举后一半的子集,因为这个数字结尾的答案将影响后一半子集的 f f 值.

时间复杂度 O(6N2) O ( 6 N 2 ) .

#include 
#define LL long long
using namespace std ;
template <class T> void Read ( T &x, char c = getchar(), bool f = 0 ) {
    for ( x = 0 ; !isdigit(c) ; c = getchar() ) f |= c == '-' ;
    for ( ; isdigit(c) ; c = getchar() ) x = 10*x + c - '0' ;
    if (f) x = -x ;
}
const int maxn = 220000, Mod = 1000000007 ;
int n, m, S, f[520][520] ;
int main() {
    int i, x, u, v, val, ans = 0 ;
    Read(n) ;
    m = 1<<9, S = m-1 ;
    for ( i = 1 ; i <= n ; i ++ ) {
        Read(x) ;
        u = x/m, v = x%m ;
        val = 1 ;
        for ( x = u^S ; x ; x = (x-1)&(u^S) )
            if (f[x|u][v]) (val += f[x|u][v]) %= Mod ;
        (val += f[u][v]) %= Mod ;
        for ( x = v ; x ; x = (x-1)&v ) (f[u][x] += val) %= Mod ;
        (f[u][0] += val) %= Mod ;
    }
    for ( i = 0 ; i <= S ; i ++ )
        (ans += f[i][0]) %= Mod ;
    (ans += Mod-n) %= Mod ;
    cout << ans << endl ;
    return 0 ;
}

你可能感兴趣的:(算法,Sol,数学,分块,DP)