Description
Solution
一道卢卡斯定理的变形。
先来看卢卡斯定理:$$C_n^m mod P = C_{n mod P}^{m mod P} * C_{n / P}^{m / P} mod P$$
在来看这道题目,题目要求我们最后的积为奇数,我们可以对于 (n),(m) 的每一个二进制位进行考虑。
当且仅当,(n = 0) 且 (m = 1) 时,(C_n^m = 0),此时积为 0,不合法。
所以我们只需要保证 (m subseteq n)。
此时,题目就变成了取出一个子序列,使得 (a_{i - 1} subseteq a_i)。
所以我们开个桶记录一下输入的每个数出现的位置,枚举每一个数,然后枚举它的二级制下的子集,判断这个子集出现的位置是否在这个数后面(题目要求不上升),如果是的话转移。
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 3e5 + 10;
const int mod = 1e9 + 7;
int n, ans;
int a[N], vis[N], f[N];
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]), vis[a[i]] = i;
for(int i = n; i >= 1; i--)
for(int j = a[i] & (a[i] - 1); j; j = a[i] & (j - 1))
if(vis[j] > i) f[i] = (f[i] + f[vis[j]] + 1) % mod;
for(int i = 1; i <= n; i++)
ans = (ans + f[i]) % mod;
printf("%d
", ans);
return 0;
}