codeforces 1017D. The Wu 思维

链接

这里写图片描述

题意比较简单,对于两个长为N的串s,t,他们配对,会按照以下规则产生”Wu”的东西。规则如下:
if si == ti : res += wi;
会得到一个综合。然后题目就是给你M个长度为N的串,以及有Q此询问,每个询问,给你个长度为N的T串,和整数K。问你M个串中有多少个串与该串匹配会产生小于K的”Wu”

思路:因为N<=12,所以最多只有4096中串,对于每个N,我们找到所有任意两个串产生的”Wu”,并记录下来,然后对于
提供的W个串,进行去重,并记录每个串的次数。因为这题,W<=100,而且所以产生的最大的”Wu”是1200,所以我们维护一个数组 book[i][j]表示编号为i的串,和W中产生J个”WU”的串有多少个。因为提前预处理任意两个串产生的WU了所以这里复杂度只有4096*4096,因为最多也只有4096个不同的串。这样我们再求一下前缀和。对于每个询问直接求t的编号,那么book[t][k]就是询问结果了。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int MAX = 4100;
const int MAX_M = 5e5+10;
int Weight[MAX];
string tostring(int x,int len){
    string res = "";
    while(x > 0){
        res += (x%2+'0');
        x /= 2;
    }
    for(int i=res.length();i<len;++i){
        res += '0';
    }
    reverse(res.begin(),res.end());
    return res;
}
char Integer[MAX][13];
int N,M,Q;
int G[MAX][MAX];
int getvalue(int u,int v){
    int res = 0;
    for(int i=0;i<N;++i){
        if(Integer[u][i] == Integer[v][i])
            res += Weight[i];
    }
    return res;
}
void init(){
    int Max = pow(2,N);
    for(int i=0;i<Max;++i){
        string str = tostring(i,N);
        for(int j=0;j<N;++j){
            Integer[i][j] = str[j];
        }
        Integer[i][N] = '\0';
    }
    for(int i=0;i<Max;++i){
        for(int j=i;j<Max;++j){
            int sum = 0;
            for(int k=0;k<N;++k){
                if(Integer[i][k] == Integer[j][k])
                    sum += Weight[k];
            }
            G[i][j] = G[j][i] = sum;
        }
    }
}
int toint(char *str){
    int res = 0;
    for(int i=0;i<N;++i){
        res = res*2 + str[i]-'0';
    }
    return res;
}
int book[MAX][1333];
int gettime[MAX];
int id[MAX_M];
bool cmp(char A[13],char B[13]){
    return strcmp(A,B) == -1;
}
int main(void){

    scanf("%d%d%d",&N,&M,&Q);
    for(int i=0;i<N;++i){
        scanf("%d",&Weight[i]);
    }
    init();
    char str[30];
    for(int i=0;i<M;++i){
        scanf("%s",str);
        int v = toint(str);
        id[i] = v;
    }
    sort(id,id+M);
    int cnt = 0;
    int last = 0;
    for(int i=0;i<M;++i){
        if(i == 0 || id[i] != id[i-1]){
            last = id[i];
            id[cnt++] = last;
            gettime[last] = 1;
        }
        else{
            gettime[last]++;
        }
    }
    int Max = pow(2,N)-1;
    for(int i=0;i<=Max;++i){
        for(int j=0;j<cnt;++j){
            int value = G[i][id[j]];
            book[i][value] += gettime[id[j]];
        }
        for(int j=1;j<=1200;++j){
            book[i][j] += book[i][j-1];
        }
    }
    char t[15];
    int k;
    long long res = 0;
    for(int i=1;i<=Q;++i){
        scanf("%s%d",t,&k);
        int v = toint(t);
        printf("%d\n",book[v][k]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhao5502169/article/details/81558107
wu