[CF1329B] Dreamoon Likes Sequences

[CF1329B] Dreamoon Likes Sequences - 计数dp

Description

有两个整数 (d, m),找到这样的数列 (a) 的数列,满足以下限制条件:

  • 数列 (a) 的长度为 (n)(n ge 1)
  • (1 le a_i lt a_2 lt cdots lt a_n le d)
  • 定义一个长度为 (n) 的数组 (b)(b_1 = a_1)(forall i ge 1, b_i = b_{i - 1} oplus a_i),其中 (oplus) 表示二进制异或 (xor)。在构建出 (b) 后,应当满足 (b_1 lt b_2 lt cdots lt b_{n - 1} lt b_n) 的限制条件。

Solution

每个 (a_i) 一定比之前的最高位要高,确定了这个最高位以后,低位就可以任意选择,只要保证选择数不超过 (d) 即可

#include <bits/stdc++.h>
using namespace std;

#define int long long

const int M = 35;
int d, m;
int f[M][M], pw[M + 1], pwm[M + 1];

void solve()
{
    cin >> d >> m;
    pw[0] = 1;
    pwm[0] = 1;
    for (int i = 1; i <= M; i++)
        pw[i] = pw[i - 1] * 2, pwm[i] = pwm[i - 1] * 2 % m;
    memset(f, 0, sizeof f);
    for (int i = 0; i < M; i++)
        if (pw[i] <= d)
            f[1][i] = min(pw[i], d - pw[i] + 1),
            f[1][i] %= m;
    for (int i = 2; i < M; i++)
    {
        for (int j = 1; j < M; j++)
        {
            for (int k = 0; k < j; k++)
            {
                if (pw[j + 1] > d)
                {
                    if (d - pw[j] >= 0)
                        f[i][j] += f[i - 1][k] * ((d - pwm[j] + 1) % m + m) % m;
                    f[i][j] %= m;
                }
                else
                {
                    f[i][j] += f[i - 1][k] * pwm[j] % m;
                    f[i][j] %= m;
                }
            }
        }
    }
    int ans = 0;
    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < M; j++)
        {
            // cout << f[i][j] << " ";
            ans += f[i][j];
            ans %= m;
        }
        // cout << endl;
    }
    cout << ans << endl;
}

signed main()
{
    ios::sync_with_stdio(false);

    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
}
原文地址:https://www.cnblogs.com/mollnn/p/14565145.html