• bzoj3687简单题(dp+bitset优化)


    3687: 简单题

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 861  Solved: 399
    [Submit][Status][Discuss]

    Description

    小呆开始研究集合论了,他提出了关于一个数集四个问题:
    1.子集的异或和的算术和。
    2.子集的异或和的异或和。
    3.子集的算术和的算术和。
    4.子集的算术和的异或和。
        目前为止,小呆已经解决了前三个问题,还剩下最后一个问题还没有解决,他决定把
    这个问题交给你,未来的集训队队员来实现。

    Input

    第一行,一个整数n。
    第二行,n个正整数,表示01,a2….,。

    Output

     一行,包含一个整数,表示所有子集和的异或和。

    Sample Input

    2
    1 3

    Sample Output

    6

    HINT

     

    【样例解释】

      6=1 异或 3 异或 (1+3)

    【数据规模与约定】

    ai >0,1<n<1000,∑ai≤2000000。

    另外,不保证集合中的数满足互异性,即有可能出现Ai= Aj且i不等于J

    /*
    设f[i]表示i出现在算术和中的次数,那么对于a[j],有f[i]+=f[i-a[j]]。最后统计哪些数出现了奇数次即可。
    */
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #define ll long long
    #define inf 1000000000
    using namespace std;
    inline ll read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int ans,n,a[1005],b[1005],f[10005],bin[25];
    void getans(int x)
    {
        int tot=0;
        for(int i=1;i<=x;i++)
            tot+=b[i];
        ans^=tot;
    }
    void dfs(int k,int last)
    {
        if(k==n)return;
        for(int i=last+1;i<=n;i++)
        {
            b[k+1]=a[i];
            getans(k+1);
            dfs(k+1,i);
        }
    }
    void solve1()
    {ans=0;dfs(0,0);printf("%d
    ",ans);}
    void solve2()
    {
        ans=0;f[0]=1;
        for(int i=1;i<=n;i++)
            for(int j=10000;j>=a[i];j--)
                f[j]+=f[j-a[i]];
        for(int i=1;i<=10000;i++)
            if(f[i]%2)ans^=i; 
        printf("%d
    ",ans);
    }
    int main()
    {
        bin[1]=1;for(int i=2;i<=24;i++)bin[i]=bin[i-1]*2;
        n=read();
        for(int i=1;i<=n;i++)
            a[i]=read();
        if(n<=10)solve1();
        else solve2();
        return 0;
    }
    暴力 %%%黄学长
    /*
    这道题f[i]表示和为i的集合个数为奇数还是偶数,
    f<<x表示f集合加上x后的集合,每次加入一个数,就用原集合异或一下这个集合就可以了。
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<bitset>
    
    using namespace std;
    bitset<2000017>f;
    int n,m,x,ans;
    
    int main()
    {
        scanf("%d",&n);f[0]=1;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            f^=(f<<x),m+=x;
            cout<<f[i]<<endl;
        }
        for(int i=1;i<=m;i++)
        {
            if(f[i]) ans^=i;
        }
        printf("%d
    ",ans);
        return 0;
    } 
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    《House of Cards》观后感
    几个常见的壳的脱壳
    【转】Arp的攻防实战
    Back Track 5 之 漏洞攻击 && 密码攻击 && Windows下渗透工具
    Back Track 5 之 Web踩点 && 网络漏洞
    Back Track 5 之 网络踩点(二)
    Back Track 5 之 网络踩点
    51单片机总线与非总线的程序对比
    关于PHP写的投票网站之刷票终结版
    关于PowerShell中的命令的别名
  • 原文地址:https://www.cnblogs.com/L-Memory/p/7074446.html
Copyright © 2020-2023  润新知