Codeforces Round 1075 (Div. 2)

A. 带有数字的表格

每次测试时间限制 每次测试内存限制 输入 输出
1 秒 256 MB 标准输入 标准输出

题目描述

Peter 画了一张大小为 $h \times l$ 的表格,里面初始填满了零。我们将其行从上到下编号为 $1$ 到 $h$,列从左到右编号为 $1$ 到 $l$。

Ned 提出了一个数字数组 $a_1, a_2, \dots, a_n$,并想要修改该表格。

Ned 的操作规则如下:

  1. 从他的数组中选择 $2k$ 个数字(其中 $2k \le n$)。
  2. 将这 $2k$ 个数字分成 $k$ 对。
  3. 对于每一对 $(x, y)$,他获取位于行 $x$ 和列 $y$ 的单元格,并将 $1$ 添加到该单元格中的数字。
  4. 如果这样的单元格不存在(即 $x > h$ 或 $y > l$),则该对对表格不执行任何操作。

Peter 支持 Ned 的倡议,并要求他最大化表中数字的总和。请帮助 Ned 计算他能达到的最大总和是多少。

输入格式

每个测试包含多个测试用例。第一行包含测试用例的数量 $t$ ($1 \le t \le 500$)。

测试用例的描述如下:

输出格式

对于每个测试用例,输出表中数字的最大可能总和。

样例

输入

7
2 1 1
1 1
5 2 2
1 2 2 3 2
8 4 2
7 2 2 2 3 4 4 2
7 3 6
10 4 1 3 5 4 6
2 4 4
5 5
7 6 3
10 4 1 3 5 4 6
4 1 1
1 1 1 1

输出

1
2
3
2
0
2
2

思路:由于GitHub的markdown格式太难调了,有时候写题解就去了一下午,有些不方便的证明我就写在纸上了,参考照片和代码。

Image

AC代码:

#include <bits/stdc++.h>
using namespace std;
// CJX__//
typedef long long ll; // 不开long long 见祖宗
typedef unsigned long long ull;
typedef __int128 i128;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<PII> vPII;
#define IOS                  \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0);
#define debug(...) cout << "[debug] " #__VA_ARGS__ " = " << (__VA_ARGS__) << endl;
#define out(x) cout << ((x) ? "YES" : "NO") << endl
#define mod(x, P) (((x) % (P) + (P)) % (P))
#define endl '\n'
#define gcd __gcd
#define lc p << 1
#define rc p << 1 | 1
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define fi first
#define se second
#define all(x) x.begin(), x.end()
#define lowbit(x) ((x) & (-x))
#define rep(i, x, n) for (ll i = x; i <= n; i++)
#define dep(i, x, n) for (ll i = x; i >= n; i--)
#define mem(a, x) memset(a, x, sizeof a)
const double eps = 1e-5;
const int N = 1e5 + 10, M = 2 * N, K = 26;
const ll MOD = 1e9 + 7, Md3 = 998244353, Md7 = 1e9 + 7, Md9 = 1e9 + 9;
const ll base1 = 131, base2 = 13331;
const int dx[8] = {-1, 0, 1, 0, -1, -1, 1, 1}, dy[8] = {0, 1, 0, -1, -1, 1, -1, 1};
const int ddx[8] = {1, 1, 2, 2, -1, -1, -2, -2}, ddy[8] = {2, -2, 1, -1, 2, -2, 1, -1};
template <typename T>
bool cmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; }
template <typename T>
bool cmax(T &a, const T &b) { return b > a ? a = b, 1 : 0; }
template <typename T>
void sort_range(vector<T> &v, int l, int r) { sort(v.begin() + l, v.begin() + r + 1); }
/*

*/

void solve()
{
    ll n, h, l;
    cin >> n >> h >> l;
    ll cnt1 = 0, cnt2 = 0, cnt3 = 0;
    rep(i, 1, n)
    {
        ll x;
        cin >> x;
        if (x <= h)
            cnt1++;
        if (x <= l)
            cnt2++;
        if (x <= h || x <= l)
            cnt3++;
    }
    cout << min({cnt1, cnt2, cnt3 / 2}) << endl;
}

int main()
{
    IOS;

    int _ = 1;
    cin >> _; // 如果是多组数据
    while (_--)
    {
        solve();
    }
    return 0;
}

B. 青蛙的诅咒

每次测试时间限制 每次测试内存限制 输入 输出
1 秒 256 MB 标准输入 标准输出

题目描述

在无限数轴上的点 $0$ 处,坐着一只青蛙。经过多年的冥想,青蛙已经掌握了 $n$ 种独特类型的魔法跳跃。

第 $i$ 种跳跃允许其向前跳转不超过 $a_i$ 个单位。换句话说,如果它位于整数点 $k$,则跳转后它可以降落在从 $k$ 到 $k+a_i$ 的任何整数点。

但魔法总是有代价的;它已经被诅咒了。在每次尝试第 $b_i$ 次使用第 $i$ 种跳跃类型之前(即在使用第 $i$ 种跳跃的第 $b_i$ 次、第 $2b_i$ 次、第 $3b_i$ 次……之前),青蛙都会回滚 $c_i$ 个单位!

换句话说,如果它在点 $k$ 且触发了回滚,它首先会发现自己在点 $k-c_i$,跳转后,它可以降落在从 $k-c_i$ 到 $k-c_i+a_i$ 的任何整数点。

青蛙的目标是到达数字为 $x$ 的点。请帮助青蛙找出它在到达目标的过程中必须忍受的最少回滚次数,或者确定它无法到达点 $x$。

输入格式

每个测试包含多个测试用例。第一行包含测试用例的数量 $t$ ($1 \le t \le 10^4$)。

测试用例的描述如下:

保证所有测试用例的 $n$ 之和不超过 $10^5$。

输出格式

对于每个测试用例,如果青蛙可以到达点 $x$,请输出它为此必须忍受的最小回滚次数。如果无法到达点 $x$,则输出 $-1$。

样例

输入

6
1 1
3 3 3
1 7
4 2 5
2 4
1 2 3
2 2 4
5 8
12 1 11
10 1 4
1 1 3
1 2 5
2 1 7
1 1000000000000000000
1000000 4 654321
1 10
2 2 1

输出

0
1
-1
2
298892990032
3

思路:贪心,我们可以计算所有技能恰好都不回退时能走far这么远,记录一个mx,为一个周期(恰好回退时走了多远)走的最大值,如果我们算出far和mx后呢,如果far>目标值,意味着我们不用回退任何一次就能达到目标,如果达不到,mx<0 那么将无法达到了,mx>0,那么剩下的路程看要多少个走多少个mx能覆盖到(上取整),
AC代码:

#include <bits/stdc++.h>
using namespace std;
// CJX__//
typedef long long ll; // 不开long long 见祖宗
typedef unsigned long long ull;
typedef __int128 i128;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<PII> vPII;
#define IOS                  \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0);
#define debug(...) cout << "[debug] " #__VA_ARGS__ " = " << (__VA_ARGS__) << endl;
#define out(x) cout << ((x) ? "YES" : "NO") << endl
#define mod(x, P) (((x) % (P) + (P)) % (P))
#define endl '\n'
#define gcd __gcd
#define lc p << 1
#define rc p << 1 | 1
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define fi first
#define se second
#define all(x) x.begin(), x.end()
#define lowbit(x) ((x) & (-x))
#define rep(i, x, n) for (ll i = x; i <= n; i++)
#define dep(i, x, n) for (ll i = x; i >= n; i--)
#define mem(a, x) memset(a, x, sizeof a)
const double eps = 1e-5;
const int N = 1e5 + 10, M = 2 * N, K = 26;
const ll MOD = 1e9 + 7, Md3 = 998244353, Md7 = 1e9 + 7, Md9 = 1e9 + 9;
const ll base1 = 131, base2 = 13331;
const int dx[8] = {-1, 0, 1, 0, -1, -1, 1, 1}, dy[8] = {0, 1, 0, -1, -1, 1, -1, 1};
const int ddx[8] = {1, 1, 2, 2, -1, -1, -2, -2}, ddy[8] = {2, -2, 1, -1, 2, -2, 1, -1};
template <typename T>
bool cmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; }
template <typename T>
bool cmax(T &a, const T &b) { return b > a ? a = b, 1 : 0; }
template <typename T>
void sort_range(vector<T> &v, int l, int r) { sort(v.begin() + l, v.begin() + r + 1); }
/*

*/

void solve()
{
    ll n, x;
    cin >> n >> x;
    ll far = 0, mx = -INF;
    rep(i, 1, n)
    {
        ll a, b, c;
        cin >> a >> b >> c;
        far += (b - 1) * a;
        ll d = a * b - c;
        cmax(mx, d);
    }
    if (far >= x)
    {
        cout << 0 << endl;
        return;
    }
    if (mx <= 0)
    {
        cout << -1 << endl;
        return;
    }
    cout << ((x - far) + mx - 1) / mx << endl;
}

int main()
{
    IOS;

    int _ = 1;
    cin >> _; // 如果是多组数据
    while (_--)
    {
        solve();
    }
    return 0;
}

C1. 异或便利 (简易版)

每次测试时间限制 每次测试内存限制 输入 输出
2 秒 256 MB 标准输入 标准输出

题目描述

这是问题的简单版本。版本之间的区别在于,在此版本中 $2 \le i \le n-1$。请注意,困难版本的正确解决方案不一定是简单版本的正确解决方案。

给定一个自然数 $n$。请找到一个长度为 $n$ 的排列 $p$,使得对于每个 $i$ ($2 \le i \le n-1$),都存在一个 $j$ ($i \le j \le n$) 满足:
$$p_i = p_j \oplus i$$

可以证明,在问题的约束下,至少存在一种合适的排列 $p$。

输入格式

每个测试包含多个测试用例。第一行包含测试用例的数量 $t$ ($1 \le t \le 10^4$)。

测试用例的描述如下:

保证所有测试用例的 $n$ 之和不超过 $2 \cdot 10^5$。

输出格式

对于每个测试用例,输出 $n$ 个整数 $p_1, p_2, \dots, p_n$ —— 即你找到的排列 $p$。

如果有多个解决方案,您可以输出其中任何一个。

样例

输入

2
3
6

输出

2 1 3
3 6 2 5 1 4

赛时思路:我在第一次写的时候想的是最朴素的解法,就给最后一个位置放1,后面填的数用数组存着,再开st数组标记哪些数已经被用过了。就从后往前一路填,当然这样很容易tle,不过我加上了一些优化居然过了,可能是数据水了,再加上这场不会被hack,所有...总之这种方法不可取
思路:
其实核心思路和最初的朴素解法是一致的。我们需要满足题目要求的下标范围是 $[2, n-1]$。

我们的策略是:先固定最后一个位置为 1,即令 $p_n = 1$。

为什么选择填 1?

我们利用 $i \oplus 1$ 的性质,结果分为两种情况:

从 $2$ 到 $n-1$,下标不断进行奇偶交替。我们发现 $2^ 1 = 3$,$3 ^ 1 = 2$。在连续下标的基础上,$i ^ 1$ 本质上是奇偶位值的互换。因此,中间部分得到的就是一段连续互换的结果,我们可以直接根据下标求出对应的值。

下标为 1 的位置该填什么?

下标 $1$ 不必满足异或条件的限制,唯一的限制是必须构成全排列(即不能使用后面已经填过的数)。通过观察 $n$ 的奇偶性,我们发现:

代码:

cpp
#include <bits/stdc++.h>
using namespace std;
// CJX__//
typedef long long ll; // 不开long long 见祖宗
typedef unsigned long long ull;
typedef __int128 i128;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<PII> vPII;
#define IOS                  \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0);
#define debug(...) cout << "[debug] " #__VA_ARGS__ " = " << (__VA_ARGS__) << endl;
#define out(x) cout << ((x) ? "YES" : "NO") << endl
#define mod(x, P) (((x) % (P) + (P)) % (P))
#define endl '\n'
#define gcd __gcd
#define lc p << 1
#define rc p << 1 | 1
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define fi first
#define se second
#define all(x) x.begin(), x.end()
#define lowbit(x) ((x) & (-x))
#define rep(i, x, n) for (ll i = x; i <= n; i++)
#define dep(i, x, n) for (ll i = x; i >= n; i--)
#define mem(a, x) memset(a, x, sizeof a)
const double eps = 1e-5;
const int N = 1e5 + 10, M = 2 * N, K = 26;
const ll MOD = 1e9 + 7, Md3 = 998244353, Md7 = 1e9 + 7, Md9 = 1e9 + 9;
const ll base1 = 131, base2 = 13331;
const int dx[8] = {-1, 0, 1, 0, -1, -1, 1, 1}, dy[8] = {0, 1, 0, -1, -1, 1, -1, 1};
const int ddx[8] = {1, 1, 2, 2, -1, -1, -2, -2}, ddy[8] = {2, -2, 1, -1, 2, -2, 1, -1};
template <typename T>
bool cmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; }
template <typename T>
bool cmax(T &a, const T &b) { return b > a ? a = b, 1 : 0; }
template <typename T>
void sort_range(vector<T> &v, int l, int r) { sort(v.begin() + l, v.begin() + r + 1); }
/*

*/

void solve()
{
    ll n;
    cin >> n;
    vll p(n + 1, 0);
    p[n] = 1;
    if (n & 1)
    {
        p[1] = n - 1;
    }
    else
    {
        p[1] = n;
    }
    rep(i, 2, n - 1)
    {
        p[i] = 1 ^ i;
    }
    rep(i, 1, n) cout << p[i] << " ";
    cout << endl;
}

int main()
{
    IOS;

    int _ = 1;
     cin>>_;//如果是多组数据
    while (_--)
    {
        solve();
    }
    return 0;
}

C2. 异或便利 (困难版)

每次测试时间限制 每次测试内存限制 输入 输出
2 秒 256 MB 标准输入 标准输出

题目描述

这是问题的困难版本。版本之间的区别在于,在此版本中 $1 \le i \le n-1$。请注意,困难版本的正确解决方案不一定是简单版本的正确解决方案。

给定一个正整数 $n$。请找到一个长度为 $n$ 的排列 $p$,使得对于每个 $i$ ($1 \le i \le n-1$),都存在一个 $j$ ($i \le j \le n$) 满足:
$$p_i = p_j \oplus i$$

或者确定不存在这样的排列。

输入格式

每个测试包含多个测试用例。第一行包含测试用例的数量 $t$ ($1 \le t \le 10^4$)。

测试用例的描述如下:

保证所有测试用例的 $n$ 之和不超过 $2 \cdot 10^5$。

输出格式

对于每个测试用例,如果存在合适的排列,则输出 $n$ 个整数 $p_1, p_2, \dots, p_n$ —— 即你找到的排列 $p$。否则,输出 $-1$。

如果存在多个解,则输出其中任何一个。

样例

输入

2
3
4

输出

2 1 3
-1

思路:

解题思路与证明

我们通过固定 $p_n = 1$ 来简化问题,对于所有 $i \in [2, n-1]$,只要令 $p_i = p_n \oplus i = 1 \oplus i$,即可始终选择 $j = n$ 来满足题目条件 $p_i = p_j \oplus i$。

利用 $x \oplus 1$ 的性质(相邻的偶奇数互换,如 $2 \leftrightarrow 3$),该构造本质上是对区间内的数进行两两交换:

此方案保证了每个 $i$ 都能找到 $j=n$ 满足等式,且所有填入的数恰好构成 $1$ 到 $n$ 的全排列。

代码:

cpp
#include <bits/stdc++.h>
using namespace std;
// CJX__//
typedef long long ll; // 不开long long 见祖宗
typedef unsigned long long ull;
typedef __int128 i128;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<PII> vPII;
#define IOS                  \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0);
#define debug(...) cout << "[debug] " #__VA_ARGS__ " = " << (__VA_ARGS__) << endl;
#define out(x) cout << ((x) ? "YES" : "NO") << endl
#define mod(x, P) (((x) % (P) + (P)) % (P))
#define endl '\n'
#define gcd __gcd
#define lc p << 1
#define rc p << 1 | 1
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define fi first
#define se second
#define all(x) x.begin(), x.end()
#define lowbit(x) ((x) & (-x))
#define rep(i, x, n) for (ll i = x; i <= n; i++)
#define dep(i, x, n) for (ll i = x; i >= n; i--)
#define mem(a, x) memset(a, x, sizeof a)
const double eps = 1e-5;
const int N = 1e5 + 10, M = 2 * N, K = 26;
const ll MOD = 1e9 + 7, Md3 = 998244353, Md7 = 1e9 + 7, Md9 = 1e9 + 9;
const ll base1 = 131, base2 = 13331;
const int dx[8] = {-1, 0, 1, 0, -1, -1, 1, 1}, dy[8] = {0, 1, 0, -1, -1, 1, -1, 1};
const int ddx[8] = {1, 1, 2, 2, -1, -1, -2, -2}, ddy[8] = {2, -2, 1, -1, 2, -2, 1, -1};
template <typename T>
bool cmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; }
template <typename T>
bool cmax(T &a, const T &b) { return b > a ? a = b, 1 : 0; }
template <typename T>
void sort_range(vector<T> &v, int l, int r) { sort(v.begin() + l, v.begin() + r + 1); }
/*

*/

void solve()
{
    ll n;
    cin >> n;
    if (n - lowbit(n) == 0)
    {
        cout << -1 << endl;
        return;
    }
    vll p(n + 1, 0);
    if (n & 1)
    {
        p[n] = 1;
        p[1] = n - 1;
        rep(i, 2, n - 1)
        {
            p[i] = 1 ^ i;
        }
    }
    else
    {
        p[n] = 1;
        p[1] = lowbit(n) ^ 1;
        rep(i, 2, n - 1)
        {
            if (i == lowbit(n))
            {
                p[i] = n;
            }
            else
            {
                p[i] = 1 ^ i;
            }
        }
    }
    rep(i, 1, n) cout << p[i] << " ";
    cout << endl;
}

int main()
{
    IOS;

    int _ = 1;
    cin >> _; // 如果是多组数据
    while (_--)
    {
        solve();
    }
    return 0;
}

D1. 小字符串 (简单版)

每次测试时间限制 每次测试内存限制 输入 输出
2 秒 256 MB 标准输入 标准输出

题目描述

这是问题的简单版本。版本之间的区别在于,在此版本中保证字符串 $s$ 不包含字符 ?

对于由字符 01 组成的字符串 $w_1w_2\dots w_n$,我们将 $f(w)$ 定义为数组 $[0,1,\dots,n-1]$ 的排列 $p_1,p_2,\dots,p_n$ 的数量,使得对于从 $1$ 到 $n$ 的所有 $i$,满足以下条件:

给定一个由字符 01 组成的字符串 $s_1s_2\dots s_n$ 以及一个正整数 $c$。注意在此版本的问题中,字符串 $s$ 不包含 ?。考虑所有可以通过将 $s$ 中的所有 ? 字符替换为 01 获得的字符串 $w$(在此版本中,只有 $w=s$ 这一种情况)。

请在所有此类字符串 $w$ 中,找到 $f(w)$ 不能被 $c$ 整除的最小值,或者确定不存在这样的字符串 $w$。由于答案可能很大,请输出其对 $10^9+7$ 取模后的结果。

输入格式

每个测试包含多个测试用例。第一行包含测试用例的数量 $t$ ($1 \le t \le 10^4$)。

测试用例的描述如下:

保证所有测试用例的 $n$ 之和不超过 $2 \cdot 10^5$。

输出格式

对于每个测试用例,如果存在这样的字符串 $w$(可以通过替换 $s$ 中的 ? 得到),使得 $f(w)$ 不能被 $c$ 整除,则输出所有此类字符串 $w$ 中 $f(w)$ 的最小值。答案应对 $10^9+7$ 取模。

如果不存在这样的字符串,则输出 $-1$。

样例

输入

9
3 3
001
3 1
111
4 100
1001
6 100
111001
6 100
111101
5 8
10001
4 100
1110
21 123456789
111000111000111000111
3 4
101

输出

-1
-1
4
96
64
12
-1
336892528
2

思路:其实可以看成0>n-1这个在不断的插数,如果si=='1‘我们可以插在数字区间的左边或者右边,贡献为2,如果si==‘0’我们要从前面的数字区间插入以破坏连续区间构成的mex值贡献为i,我们默认字符串从0开始。注意不要被c恰好整除
代码:

cpp
#include <bits/stdc++.h>
using namespace std;
// CJX__//
typedef long long ll; // 不开long long 见祖宗
typedef unsigned long long ull;
typedef __int128 i128;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<PII> vPII;
#define IOS                  \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0);
#define debug(...) cout << "[debug] " #__VA_ARGS__ " = " << (__VA_ARGS__) << endl;
#define out(x) cout << ((x) ? "YES" : "NO") << endl
#define mod(x, P) (((x) % (P) + (P)) % (P))
#define endl '\n'
#define gcd __gcd
#define lc p << 1
#define rc p << 1 | 1
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define fi first
#define se second
#define all(x) x.begin(), x.end()
#define lowbit(x) ((x) & (-x))
#define rep(i, x, n) for (ll i = x; i <= n; i++)
#define dep(i, x, n) for (ll i = x; i >= n; i--)
#define mem(a, x) memset(a, x, sizeof a)
const double eps = 1e-5;
const int N = 1e5 + 10, M = 2 * N, K = 26;
const ll MOD = 1e9 + 7, Md3 = 998244353, Md7 = 1e9 + 7, Md9 = 1e9 + 9;
const ll base1 = 131, base2 = 13331;
const int dx[8] = {-1, 0, 1, 0, -1, -1, 1, 1}, dy[8] = {0, 1, 0, -1, -1, 1, -1, 1};
const int ddx[8] = {1, 1, 2, 2, -1, -1, -2, -2}, ddy[8] = {2, -2, 1, -1, 2, -2, 1, -1};
template <typename T>
bool cmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; }
template <typename T>
bool cmax(T &a, const T &b) { return b > a ? a = b, 1 : 0; }
template <typename T>
void sort_range(vector<T> &v, int l, int r) { sort(v.begin() + l, v.begin() + r + 1); }

/*

*/

void solve()
{
    ll n, c;
    cin >> n >> c;
    string s;
    cin >> s;
    if (s.back() == '0')
    {
        cout << -1 << endl;
        return;
    }
    ll ans = 1, res = 1;
    rep(i, 0, n - 2)
    {
        if (s[i] == '1')
        {
            ans = (ans * 2) % Md7;
            res = (res * 2) % c;
        }
        else
        {
            ans = (ans * i) % Md7;
            res = (res * i) % c;
        }
    }
    if (res == 0)
    {
        cout << -1 << endl;
    }
    else
    {
        cout << ans << endl;
    }
}

int main()
{
    IOS;

    int _ = 1;
    cin >> _; // 如果是多组数据
    while (_--)
    {
        solve();
    }
    return 0;
}

Image

Image

D2也差不多,给代码算了,思路差不多,只是判断整除麻烦.
代码:
```cpp
#include <bits/stdc++.h>
using namespace std;
// CJX__//
typedef long long ll; // 不开long long 见祖宗
typedef unsigned long long ull;
typedef __int128 i128;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<PII> vPII;
#define IOS                  \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0);
#define debug(...) cout << "[debug] " #__VA_ARGS__ " = " << (__VA_ARGS__) << endl;
#define out(x) cout << ((x) ? "YES" : "NO") << endl
#define mod(x, P) (((x) % (P) + (P)) % (P))
#define endl '\n'
#define gcd __gcd
#define lc p << 1
#define rc p << 1 | 1
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define fi first
#define se second
#define all(x) x.begin(), x.end()
#define lowbit(x) ((x) & (-x))
#define rep(i, x, n) for (ll i = x; i <= n; i++)
#define dep(i, x, n) for (ll i = x; i >= n; i--)
#define mem(a, x) memset(a, x, sizeof a)
const double eps = 1e-5;
const int N = 1e5 + 10, M = 2 * N, K = 26;
const ll MOD = 1e9 + 7, Md3 = 998244353, Md7 = 1e9 + 7, Md9 = 1e9 + 9;
const ll base1 = 131, base2 = 13331;
const int dx[8] = {-1, 0, 1, 0, -1, -1, 1, 1}, dy[8] = {0, 1, 0, -1, -1, 1, -1, 1};
const int ddx[8] = {1, 1, 2, 2, -1, -1, -2, -2}, ddy[8] = {2, -2, 1, -1, 2, -2, 1, -1};
template <typename T>
bool cmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; }
template <typename T>
bool cmax(T &a, const T &b) { return b > a ? a = b, 1 : 0; }
template <typename T>
void sort_range(vector<T> &v, int l, int r) { sort(v.begin() + l, v.begin() + r + 1); }
/*

*/

void solve()
{
    ll n, c;
    string s;
    cin >> n >> c >> s;
    vll pos;
    if (s[0] == '?')
    {
        s[0] = '1';
    }
    if (s[0] != '1')
    {
        cout << -1 << endl;
        return;
    }
    if (s[n - 1] == '?')
    {
        s[n - 1] = '1';
    }
    if (s[n - 1] != '1')
    {
        cout << -1 << endl;
        return;
    }
    ll w = 2;
    c /= gcd(c, (ll)2);
    rep(i, 1, n - 2)
    {
        if (s[i] == '0')
        {
            c /= gcd(c, i);
            w = w * i % Md7;
        }
        else if (s[i] == '1')
        {
            c /= gcd(c, (ll)2);
            w = w * 2 % Md7;
        }
        else
        {
            if (i == 1)
                continue;
            if (i % 2 == 0)
            {
                c /= gcd(c, (ll)2);
                w = w * 2 % Md7;
            }
            else
            {
                pos.push_back(i);
            }
        }
    }
    if (c == 1)
    {
        cout << -1 << endl;
        return;
    }
    ll m = pos.size();
    ll cnt = 0;
    while (c % 2 == 0)
    {
        c /= 2;
        cnt++;
    }
    if (c != 1)
    {
        rep(i, 0, m - 1)
        {
            w = w * 2 % Md7;
        }
        cout << w << endl;
        return;
    }
    cnt = min(cnt - 1, m);
    rep(i, 0, m - cnt - 1) w = w * pos[i] % Md7;
    rep(i, 0, cnt - 1) w = w * 2 % Md7;
    cout << w << endl;
}

int main()
{
    IOS;

    int _ = 1;
     cin>>_;//如果是多组数据
    while (_--)
    {
        solve();
    }
    return 0;
}