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';
    }
}
相关推荐
汀、人工智能14 小时前
[特殊字符] 第40课:二叉树最大深度
数据结构·算法·数据库架构·图论·bfs·二叉树最大深度
沉鱼.4414 小时前
第十二届题目
java·前端·算法
大熊背15 小时前
ISP Pipeline中Lv实现方式探究之三--lv计算定点实现
数据结构·算法·自动曝光·lv·isppipeline
西岸行者16 小时前
BF信号是如何多路合一的
算法
大熊背16 小时前
ISP Pipeline中Lv实现方式探究之一
算法·自动白平衡·自动曝光
罗西的思考16 小时前
【OpenClaw】通过 Nanobot 源码学习架构---(5)Context
人工智能·算法·机器学习
Liudef0617 小时前
后量子密码学(PQC)深度解析:算法原理、标准进展与软件开发行业的影响
算法·密码学·量子计算
OYpBNTQXi18 小时前
SEAL全同态加密CKKS方案入门详解
算法·机器学习·同态加密
蚂蚁数据AntData19 小时前
破解AI“机器味“困境:HeartBench评测实践详解
大数据·人工智能·算法·机器学习·语言模型·开源
ZC跨境爬虫19 小时前
Python异步IO详解:原理、应用场景与实战指南(高并发爬虫首选)
爬虫·python·算法·自动化