洛谷 P3773 [CTSC2017]吉夫特
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\n", ans);
return 0;
}