1 条题解

  • 0
    @ 2025-8-24 23:06:34

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar huangrenheluogu
    NOIP2025 rp++||得 T2 者得天下,失 T2 者失天下

    搬运于2025-08-24 23:06:34,当前版本为作者最后更新于2025-01-04 18:09:08,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    发现性质:对于一种『选择开始认为的左/右方向,并在恰好 KK 个节点改变方向认知的方案』,最后到达的节点是不同的。证明或者感性理解都是容易的。

    因此,对于最终到达的节点计数可以转化为对路径计数。

    数位 dp,fd,k,of_{d,k,o} 表示剩余 dd 层,剩余 kk 次改变机会,走到点的权值数量/权值和是多少,转移是容易的。

    #include<bits/stdc++.h>
    #define pii pair<int, int>
    #define fi first
    #define se second
    using namespace std;
    const int N = 1005, mod = 1e9 + 7;
    int n, k, op[N], ll[N], rr[N], a[N];
    int ans1, ans2, ans, qp[N];
    char str[N];
    pii f[N][N][2];
    bool vis[N][N][2];
    inline void add(int &x, int y){
        x += y;
        if(x >= mod) x -= mod;
    }
    inline int pls(int x, int y){
        x += y;
        if(x >= mod) x -= mod;
        return x;
    }
    inline pii operator + (pii x, pii y){
        add(x.fi, y.fi), add(x.se, y.se);
        return x;
    }
    inline pii work(int d, int k, int o, int lim){
        // determine 2 ^ (d - 1)
        if(k < 0 || k > d) return {0, 0};
        if(!d) return {0, !k};
        if(!lim && vis[d][k][o]) return f[d][k][o];
        pii res = {0, 0}, tmp;
        int x, up = lim ? a[d] : 1;
        x = o ^ op[d];
        if(!lim || x <= up){
            tmp = work(d - 1, k, o, lim && (x == up));
            res = res + tmp;
            if(x) add(res.fi, 1ll * qp[d - 1] * tmp.se % mod);
        }
        x ^= 1;
        if(!lim || x <= up){
            tmp = work(d - 1, k - 1, o ^ 1, lim && (x == up));
            res = res + tmp;
            if(x) add(res.fi, 1ll * qp[d - 1] * tmp.se % mod);
        }
        if(!lim){
            vis[d][k][o] = 1;
            f[d][k][o] = res;
        }
        return res;
    }
    inline int calc(int *arr, int o){
        if(o){
            arr[n - 1]--;
            for(int i = n - 1; i && arr[i] < 0; i--){
                arr[i] += 2, arr[i - 1]--;
            }
            if(arr[0] < 0) return 0;
        }
        for(int i = 1; i < n; i++){
            a[i] = arr[i];
        }
        reverse(a + 1, a + n);
        pii res = {0, 0};
        res = res + work(n - 1, k, 0, 1);
        res = res + work(n - 1, k, 1, 1);
        int sum = 0;
        sum = res.fi;
        add(sum, 1ll * res.se * qp[n - 1] % mod);
        return sum;
    }
    int main(){
        // freopen("maze.in", "r", stdin);
        // freopen("maze.out", "w", stdout);
        scanf("%d%d%s", &n, &k, str + 1);
        for(int i = 1; i < n; i++){
            op[n - i] = (str[i] == 'L' ? 0 : 1);
        }
        scanf("%s", str);
        for(int i = 1; i < n; i++){
            ll[i] = str[i] - '0';
        }
        scanf("%s", str);
        for(int i = 1; i < n; i++){
            rr[i] = str[i] - '0';
        }
        qp[0] = 1;
        for(int i = 1; i <= n; i++){
            qp[i] = pls(qp[i - 1], qp[i - 1]);
        }
        ans1 = calc(rr, 0);
        ans2 = calc(ll, 1);
        ans = pls(ans1, mod - ans2);   
        printf("%d\n", ans);
        return 0;
    }
    
    • 1

    信息

    ID
    11015
    时间
    500ms
    内存
    500MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者