生活随笔
收集整理的這篇文章主要介紹了
loj 300 [CTSC2017]吉夫特 【Lucas定理 + 子集dp】
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題目鏈接
loj300
題解
orz litble
膜完題解后,突然有一個簡單的想法:
考慮到\(2\)是質(zhì)數(shù),考慮Lucas定理:
\[{n \choose m} = \prod_{i = 1} {\lfloor \frac{n}{2^{i - 1}} \rfloor \mod 2^i \choose \lfloor \frac{m}{2^{i - 1}} \rfloor \mod 2^i} \pmod 2\]
即
\[{n \choose m} = \prod_{each.bit.of.n.and.m} {n' \choose m'} \pmod 2\]
如果二進制下有任何一位\(n\)為\(0\)且\(m\)不為\(0\),那么就會出現(xiàn)\(m' > n'\)的項,結(jié)果就為\(0\)了
所以結(jié)果不為\(0\),當(dāng)且僅當(dāng)二進制下\(m\)是\(n\)的子集
所以枚舉子集dp即可【\(f[i]\)表示以\(A[u] = i\)的\(u\)開頭的合法子序列個數(shù)】
\([1,n]\)枚舉子集的復(fù)雜度是\(O(3^{log(max\{a_i\})})\)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 250000,maxm = 100005,INF = 1000000000,P = 1e9 + 7;
inline int read(){int out = 0,flag = 1; char c = getchar();while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}return out * flag;
}
int f[maxn],a[maxn],ans,n;
int main(){n = read();REP(i,n) a[i] = read();for (int i = n; i; i--){int u = a[i];for (int j = u; j; j = (j - 1) & u){f[u] = (f[u] + f[j]) % P;}ans = (ans + f[u]) % P;f[u]++;}printf("%d\n",ans);return 0;
}
轉(zhuǎn)載于:https://www.cnblogs.com/Mychael/p/8987024.html
總結(jié)
以上是生活随笔為你收集整理的loj 300 [CTSC2017]吉夫特 【Lucas定理 + 子集dp】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。