【LOJ】#2264. 「CTSC2017」吉夫特
阿新 • • 發佈:2018-11-11
題解
根據一番認真嚴肅的猜結論和打表證明之後
我們可以得到
\(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(); }