CSUSTOJ 你真的会加法吗?(字典树)

你真的会加法吗?
Description

众所周知,LJ精通 1 + 11+1 和 1 + 21+2 , 这天他遇到一个简单的加法题,但这个加法有一个特殊的性质,它是不进位加法,

比如当是10进制时 987 + 643 = 520987+643=520 ,当一位大于 1010 的时候我们我们对其模 1010 ,取余数作为这位的值,kk 进制数同理。

现在给你 nn 个数 (1 \leq n \leq 1e5)(1≤n≤1e5),并且每个数最多只有 1010 位,然后给定一个 kk (2 \leq k \leq 10)(2≤k≤10) ,代表所有数都是 kk 进制数,

接下来有 qq 次询问 (1 \leq q \leq 1e5)(1≤q≤1e5) ,每次询问给你一个长度不超过 1010 的 kk 进制数,你需要在 nn 个数中找到一个数和它进行

不进位加法时所得到的值最大,输出这个最大值。佳爷觉得这题太水了,就出给同学们做了。

Input
第一行两个正整数 n (1 \leq n \leq 1e5), k (2 \leq k \leq 10)n(1≤n≤1e5), k(2≤k≤10) 。

第二行 nn 个整数,每个整数最多只有 1010 位。

第三行一个整数 qq ,(1 \leq q \leq 1e5)(1≤q≤1e5)
接下来有 qq 行,代表 qq 次询问,每次给你一个位数不超过 1010 的整数。

Output
输出有 qq 行,每行对应一个询问的所求的最大值

Sample Input 1

4 10
998
997
886
885
4
991
998
119
190
Sample Output 1

889
886
995
976
Hint

输入的数字可能含有前导 00

思路:
最小异或和的变形。就是在字典树每次找最高位相加和最小的那一个点走就好了。

#include 
#include 
#include 
#include 
#include 

using namespace std;

const int maxn = 1e5 + 7;

int ch[maxn * 12][12],tot = 1;
int n,k;
char a[20];

void insert(char *s) {
    int u = 1;
    int len = strlen(s + 1);
    for(int i = 11;i >= 1;i--) {
        int id;
        if(i <= len) id = s[len - i + 1] - '0';
        else id = 0;
        if(!ch[u][id]) {
            ch[u][id] = ++tot;
        }
        u = ch[u][id];
    }
}

string query(char *s) {
    string ans;
    int u = 1;
    int len = strlen(s + 1);
    for(int i = 11;i >= 1;i--) {
        int id;
        if(i <= len) id = s[len - i + 1] - '0';
        else id = 0;
        int mx = -1,pos = 0;
        for(int j = 0;j <= 9;j++) {
            if(ch[u][j] && (j + id) % k > mx) {
                mx = (j + id) % k;
                pos = j;
            }
        }
        ans += (char)(mx + '0');
        u = ch[u][pos];
    }
    return ans;
}

int main() {
    scanf("%d%d",&n,&k);
    for(int i = 1;i <= n;i++) {
        scanf("%s",a + 1);
        insert(a);
    }
    string ans;
    int m;scanf("%d",&m);
    for(int i = 1;i <= m;i++) {
        scanf("%s",a + 1);
        ans = query(a);
        int flag = 0;
        for(int i = 0;i < ans.size();i++) {
            if(ans[i] != '0') {
                flag = 1;
                for(int j = i;j < ans.size();j++) {
                    printf("%c",ans[j]);
                }
                printf("\n");
                break;
            }
        }
        if(!flag) printf("0\n");
    }
    return 0;
}

你可能感兴趣的:(#,长理选拔赛,#,字典树)