[CTSC2017]吉夫特

版权声明:hhhhh https://blog.csdn.net/WT_cnyali/article/details/80870194

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

Click here to read the problem.

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

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

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

时间复杂度O(6N2).

#include <bits/stdc++.h>
#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 ;
}
阅读更多
换一批

没有更多推荐了,返回首页