Problem - D2 - Codeforces [插入计数]

Problem - D2 - Codeforces

trick:相对位置关系 可以插入计数

直接D1 D2一起讲解

先简单看D1 也就是没有问号的时候

那么对w的每个字符 如果是1 就有有一个子数组mex=i

反之就不能有子数组mex=i;

首先对于单个0 以及整个区间的情况 一定会有mex=1 以及mex=n;

因此w1=wn=1;

其次我们计算方案数 [插入计数]

我们可以通过插入0到n-1这些数字来构造一个合法排列

刚开始插入0 当0到k-1已经定了的时候 我们要插入k

若wk=1 那么k能插入的位置只有整个已插入数字的左右两侧 只有这样才能保证有mex=k存在

若wk=0 那么k可以插入到已经插入的相邻数字之间 已经插入了k个数字 那就有k-1个位置可以插入 这样的话当区间选到k的时候 mex不可能为k

也就是wi=1 就乘2 wi=0 就乘i;

由于取模 所以判断ans与c是否整除的时候不能最后除法判断 要在每个乘法的过程 用c/(gcd(c,x))x表示ans的因子 也就是上述乘法过程中的每个数

对于D2部分 ?可以为1 可以为0

我们要保证答案不被c整除并且答案尽可能小

那么非?部分已经确定 我们用c除以固定部分的公因数后得到c1 那么c1与剩下部分的乘积不能整除

想要尽可能小 我们肯定要尽可能选择乘2 而不是乘i

当我们全选择乘2的时候那么乘积就是一个2的次幂 如果c不是二的次幂 完全就可以这么贪心的选择

当c是二的次幂的时候 假设有x个? 那么就是x次幂 假设c是k次幂 我们要尽可能让x<k 这样就不会整除 也就是要选择问号 变为0 乘i 如果i是偶数 那么天然带2 无法降低2的次幂 我们只能选择奇数变成0 偶数必须全变成2 我们选择较小的奇数变为0 这样的话 乘的i尽可能小 答案也小

代码如下:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

#define int long long

const int mod = 1e9+7;
void solve() {
    int n, c;
    cin >> n >> c;
    string s;
    cin >> s;
    if (s[1] == '?') {
        s[1] = '0';
    }
    if (s[0] == '0' || s[n-1] == '0') {
        cout << -1;
        return;
    }
    s[0] = '1';
    s[n-1] = '1';
    vector<int> good;
    int cnt = 0;
    for (int i = 0; i < n-1; ++i) {
        if (s[i] == '0') {
            c /= gcd(c, i);
        } else if (s[i] == '1') {
            c /= gcd(c, 2ll);
        }else {
            cnt++;
            if (i % 2 == 1) {
                good.push_back(i);
            }
        }
    }
    if (c != (1 << __lg(c))) {
        int ans = 1;
        for (int i = 0; i < n-1; ++i) {
            if (s[i] == '0') {
                ans *= i;
            }else {
                ans *= 2;
            }
            ans %= mod;
        }
        cout << ans;
        return;
    }
    int w = cnt;
    int h = __lg(c);
    for (int i = 0; i < good.size(); ++i) {
        if (w < h) {
            break;
        } else {
            s[good[i]] = '0';
            w--;
        }
    }
    if (w >= h) {
        cout << -1;
        return;
    }
    int ans = 1;
    for (int i = 0; i < n-1; ++i) {
        if (s[i] == '0') {
            ans *= i;
        }else {
            ans *= 2;
        }
        ans %= mod;
    }
    cout << ans;
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1;
    cin >> t;
    while (t--) {
        solve();
        cout << '\n';
    }
}
相关推荐
图图的点云库2 小时前
点云深度学习算法概述
人工智能·深度学习·算法
2501_924952692 小时前
设计模式在C++中的实现
开发语言·c++·算法
菜鸟小九2 小时前
hot100(71-80)
java·数据结构·算法
不想看见4042 小时前
Implement Queue using Stacks栈和队列--力扣101算法题解笔记
笔记·算法·leetcode
DeepModel2 小时前
【统计检验】T检验
算法
2501_945425152 小时前
C++编译期字符串处理
开发语言·c++·算法
m0_733612212 小时前
模板编译期哈希计算
开发语言·c++·算法
ab1515172 小时前
3.18二刷基础119、124,完成进阶52
算法
Jordannnnnnnn2 小时前
复试day27
数据结构·c++·算法