1. 程式人生 > >【LOJ】#2264. 「CTSC2017」吉夫特

【LOJ】#2264. 「CTSC2017」吉夫特

題解

根據一番認真嚴肅的猜結論和打表證明之後
我們可以得到
\(f[i] = \sum_{a[i] & a[j] == a[j]} f[j] + 1\)
統計所有的\(f[i] - 1\)

然後對於這道題,我們可以從值域上直接做

就是\(g[a]\)表示\(a\)作為結尾的數的序列有多少個

每次從\(a\)轉移到\(a\)的子集\(b\),同時要滿足\(pos[b] > pos[a]\)

程式碼

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define space putchar(' ')
#define enter putchar('\n')
#define MAXN 240005
//#define ivorysi
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) out(x / 10);
    putchar('0' + x % 10);
}
const int MOD = 1000000007;
int N;
int a[MAXN],pos[MAXN],ans,f[MAXN];
int inc(int a,int b) {
    return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
    return 1LL * a * b % MOD;
}
void update(int &x,int y) {
    x = inc(x,y);
}
void Solve() {
    int t = 0;
    read(N);
    for(int i = 1 ; i <= N ; ++i) {
    read(a[i]);pos[a[i]] = i;t = max(t,a[i]);
    }
    
    for(int S = t ; S ; --S) {
    if(!pos[S]) continue;
    update(ans,f[S]);
    update(f[S],1);
    for(int T = (S - 1) & S ; T ; T = (T - 1) & S) {
        if(!pos[T]) continue;
        if(pos[T] > pos[S]) update(f[T],f[S]);
    }
    }
    out(ans);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
}