Codeforces Round #502 D. The Wu

题目地址:http://codeforces.com/contest/1017/problem/D
因为集合里和询问中有许多重复的,可以进行预处理,复杂度大概是4096 * 4096 * 12

1096ms的代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int N = 4100;
int n,m,q;
int w[15];
int flag[N];
int ans[N][105];
char s[15];

int zhuanhuan(char a[])
{
    int len = strlen(a);
    //printf("%d\n",len);
    int sum = 0;
    int x = 1;
    for(int i = len - 1;i >= 0;--i)
    {
        if(a[i] == '1'){
            sum += x;
        }
        x = x * 2;
    }
    return sum;
}

int main()
{
//    char tmp[5] = "0110";
//    printf("%d\n",zhuanhuan(tmp));
    while(~scanf("%d %d %d",&n,&m,&q))
    {
        for(int i = 0;i < n;++i)
        {
            scanf("%d",&w[i]);
        }
        memset(flag,0,sizeof(flag));
        memset(ans,0,sizeof(ans));
        for(int i = 0;i < m;++i)
        {
            scanf("%s",s);
            flag[zhuanhuan(s)]++;
        }
//        for(int i = 0;i < 4;++i)
//        {
//            printf("%d ",flag[i]);
//        }
//        printf("\n");
        for(int i = 0;i < N;++i)
        {
            for(int j = 0;j < N;++j)
            {
                if(flag[j] != 0){
                    int sum = 0;
                    int p = i ^ j;
                    //printf("%d\n",p);
                    for(int k = 0;k < n;++k)
                    {
                        //printf("%d %d\n",k,p);
                        if((p & 1) == 0){
                            sum += w[n - k - 1];
                        }
                        p >>= 1;
                    }
                    //printf("i:%d j:%d flag[j]:%d sum:%d p:%d\n",i,j,flag[j],sum,p);
//                    for(int k = sum;k <= 100;++k)
//                    {
//                        ans[i][k] += flag[j];
//                    }
                    if(sum <= 100){
                        ans[i][sum] += flag[j];
                    }
                }
            }
        }
        for(int i = 0;i < N;++i)
        {
            for(int j = 1;j <= 100;++j)
            {
                ans[i][j] += ans[i][j - 1];
            }
        }
        for(int i = 0;i < q;++i)
        {
            char tmp[15];int k;
            scanf("%s %d",tmp,&k);
            printf("%d\n",ans[zhuanhuan(tmp)][k]);
        }
    }
    return 0;
}

498ms

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int N = 4100;
int n,m,q;
int w[15];
int flag[N];
int ans[N][105];
char s[15];
int g[N];

int zhuanhuan(char a[])
{
    int len = strlen(a);
    //printf("%d\n",len);
    int sum = 0;
    int x = 1;
    for(int i = len - 1;i >= 0;--i)
    {
        if(a[i] == '1'){
            sum += x;
        }
        x = x * 2;
    }
    return sum;
}

int main()
{
//    char tmp[5] = "0110";
//    printf("%d\n",zhuanhuan(tmp));
    while(~scanf("%d %d %d",&n,&m,&q))
    {
        for(int i = 0;i < n;++i)
        {
            scanf("%d",&w[i]);
        }
        memset(flag,0,sizeof(flag));
        memset(ans,0,sizeof(ans));
        memset(g,0,sizeof(g));
        for(int i = 0;i < m;++i)
        {
            scanf("%s",s);
            flag[zhuanhuan(s)]++;
        }
//        for(int i = 0;i < 4;++i)
//        {
//            printf("%d ",flag[i]);
//        }
//        printf("\n");
        //比上面优化的是预处理了一下每一个数二进制位为1时会得到wu值,最后会得到“wu”值总和
        for (int i = 0;i < N;i++)
        {
            for (int j = 0,k = 1;j < n;j++,k *= 2){
                if ((i & k) != 0)
                    g[i] += w[n - j - 1];
            }
        }
        for(int i = 0;i < (1 << n);++i)
        {
            for(int j = 0;j < (1 << n);++j)
            {
                if(flag[j] != 0){
                    int sum = 0;
                    int p = i ^ j;
                    sum = g[(1 << n) - p - 1];
                    //printf("i:%d j:%d sum:%d flag:%d\n",i,j,sum,flag[j]);
                    if(sum <= 100){
                        ans[i][sum] += flag[j];
                    }
                }
            }
        }
        for(int i = 0;i < N;++i)
        {
            for(int j = 1;j <= 100;++j)
            {
                ans[i][j] += ans[i][j - 1];
            }
        }
        for(int i = 0;i < q;++i)
        {
            char tmp[15];int k;
            scanf("%s %d",tmp,&k);
            printf("%d\n",ans[zhuanhuan(tmp)][k]);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36386435/article/details/81544554