Subtask 0\texttt{Subtask 0}

爆搜。或者直接输出 mm

Subtask 0.5\texttt{Subtask 0.5}

aia_i 为最终赢到 ii 澳元的方案数,cic_i 表示是否有面值为 ii 的筹码(有为 11,没有为 00),则 ana_n 为答案。

递推式:

a1=c1a_1=c_1 $$a_{i+1}=(a_{\lceil\frac{i+1}{2}\rceil}+\ldots+a_{i-1}+a_i)+c_{i+1} $$

时间 / 空间复杂度为 O(n2+m)/O(n+m)O(n^2+m)/O(n+m)

Subtask 1\texttt{Subtask 1}

bib_iaia_i 的前缀和(b1=a1b_1=a_1bi=bi1+aib_i=b_{i-1}+a_i),注意到 $\lceil\dfrac{i+1}{2}\rceil=\lfloor\dfrac{i}{2}\rfloor+1$,则 bnbn1b_n-b_{n-1} 为答案。

b1=c1b_1=c_1 $$b_{i+1}=(b_i+b_i-b_{\lfloor\frac{i}{2}\rfloor})+c_{i+1} $$

时间 / 空间复杂度为 O(n+m)/O(n+m)O(n+m)/O(n+m)

Subtask 2\texttt{Subtask 2}

不难发现,求 bi+1b_{i+1} 时只需要 bib_ibi2b_{\lfloor\frac{i}{2}\rfloor} 的值。于是,我们可以每次只存 $b_i,b_{\lfloor\frac{i}{2}\rfloor},b_{\lfloor\frac{i}{4}\rfloor},b_{\lfloor\frac{i}{8}\rfloor},\ldots,b_1$ 的值。例如:

ii 存储的下标
11
22 2,12,1
33 3,13,1
44 4,2,14,2,1
55 5,2,15,2,1
66 6,3,16,3,1
77 7,3,17,3,1
88 8,4,2,18,4,2,1
\ldots

不难发现,每次从右往前更新即可。时间 / 空间复杂度为 O(n+m)/O(m+logn)O(n+m)/O(m+ \log n)

参考代码(std)

#include <bits/stdc++.h>
using namespace std;
const int B = 32, P = 1e9 + 7, M = 1e6 + 5;
int b[B], p[B], a[M];
int main()
{
    int n, m, s = 0;
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
        cin >> a[i];
    for (int i = 1; i <= n; i++)
    {
        int t = i & (-i);
        for (int j = 1, k = 1, l = i; k <= t; j++, k <<= 1, l >>= 1)
        {
            b[j] <<= 1;
            b[j] -= b[j + 1];
            if (p[j] != m && a[p[j] + 1] == l) b[j]++, p[j]++;
            b[j] %= P;
            if (b[j] < 0) b[j] += P;
        }
        if (i == n - 1) s -= b[1];
        if (i == n) s += b[1];
    }
    cout << (s % P + P) % P;
    return 0;
}