• Gym101889E. Enigma(bfs+数位)


    比赛链接:传送门

    题目大意:

      求一个十进制大数S(有部分数位为"?")能被N整除时的最小值,如果没有办法被N整除,输出"*"。

    思路:

      一个数位上的数值增加1后,对N取模时的贡献可以预处理出来。设为mod[MAX_N]。

      先把整个十进制大数置成最小的合法状态,存在res中。(问号置为0或1)

      此时的大数对N取模的值是可以计算的。设为val。

      如果val为0,res中已经是最大的答案。

      如果val不为0,从最右边的"?"开始往左枚举"?"。

      维护一个vis数组,vis[k] = true表示已经访问过的问号当中,至少有一种填法使得整个大数对N取模的余数为k。

      如果vis[N-val] = true,说明找到了一种填法。因为是从右往左枚举"?"的,第一次得到vis[N-val] = true时,几乎就是最小的了。考虑到当前数位填的数相同时,可能在当前的"?"右边的"?"填数不同,可能导致最小值不同,所以要额外judge一下。更新vis数组时,记录路径,在vis[N-val] = true时,反演路径,对应修改res中对应数位的数值即可。

    代码:

    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAX_N = 1000 + 5;
    const int INF = 0x3f3f3f3f;
    
    int N;//取模
    int len;//S的长度
    char S[MAX_N], res[MAX_N];
    int mod[MAX_N];//数位取模的值
    int val;//work构造模N为val的值
    bool vis[MAX_N], tmpvis[MAX_N];//vis[i]能否构造模N为i的值
    int fat[MAX_N], fatnum[MAX_N], fatlog[MAX_N];//记录路径
    
    inline bool judge(int pos, int l, int n, int f)
    {
        if (l == fatlog[fat[pos]]) {
            return n < fatnum[fat[pos]];
        }
        return l < fatlog[fat[pos]];
    }
    
    bool work()
    {
        memset(vis, false, sizeof vis);
        vis[0] = true;
        fat[0] = -1;
        fatnum[0] = 0;
        fatlog[0] = 0;
        if (vis[val])
            return true;
    
        for (int i = 1; i <= len; i++) {
            int p = len-i;
            if (isdigit(S[p]))
                continue;
            memcpy(tmpvis, vis, sizeof vis);
            for (int j = 1+(i==len); j <= 9; j++) {
                for (int k = 0; k < N; k++) if(vis[k]) {
                    int pos = ( k+mod[i]*(j - (i==len)) )%N;
                    if (!tmpvis[pos] || judge(pos, i, j, k)) {
                        tmpvis[pos] = true;
                        //可能同时有很多边找到了?不可能。
                        fat[pos] = k;
                        fatnum[pos] = j;
                        fatlog[pos] = i;
                    }
                }
                if (tmpvis[val])
                    return true;
            }
            memcpy(vis, tmpvis, sizeof vis);
        }
        return false;
    }
    
    int main()
    {
    //    freopen("testdata.txt", "r", stdin);
        while (~scanf("%s%d", S, &N)) {
    
            len = strlen(S);
            mod[1] = 1%N;
            for (int i = 2; i <= len; i++) {
                mod[i] = mod[i-1]*10%N;
            }
    
            val = 0;
            for (int i = 1; i <= len; i++) {
                int p = len-i;
                res[p] = S[p];
                if (isdigit(S[p])) {
                    val += (S[p]-'0')*mod[i]%N, val %= N;
                }
                else if (S[p] == '?') {
                    if (i == len) {
                        val += mod[i]%N, val %= N;
                        res[p] = '1';
                    }
                    else {
                        res[p] = '0';
                    }
                }
            }
            val = (N-val)%N;
            res[len] = '';
        //    printf("%s
    ", res);
    
            bool ans = work();
            if (!ans) {
                puts("*");
                continue;
            }
    
            int tmp = val;
            while (fat[tmp] != -1) {
                int f = fat[tmp];
                int l = fatlog[tmp];
                int n = fatnum[tmp];
                int pos = len-l;
                res[pos] = n + '0';
                tmp = f;
            }
    //        printf("%s
    ", S);
            printf("%s
    ", res);
    //        puts("");
        }
        return 0;
    }
    /*
    1??????????????????????????????? 2
    
    ???????????????????????????????1 2
    
    ?294?? 17
    
    9999??????? 81
    */
    View Code
  • 相关阅读:
    work 2
    chapter02
    7.23作业
    第五章
    三层交换机
    基于nginx结合openssl实现https
    chapter10--进程和计划任务管理
    Linux系统管理08--服务器RAID及配置实战
    chapter07-- LVM逻辑卷
    Linux系统管理07--文件系统与LVM
  • 原文地址:https://www.cnblogs.com/Lubixiaosi-Zhaocao/p/9980198.html
Copyright © 2020-2023  润新知