51Nod 1684 子集价值 (平方和去括号技巧)

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1684

题意:

新建一个位运算,求所有子集通过这个位运算后的答案的平方和是多少。

先想弱化版:

新建一个位运算,求所有子集通过这个位运算后的答案的和是多少。

枚举每一个二进制位,看有多少个子集能够使这一位为1

dp[i]表示前i个数中,能使枚举的这一位为1的方案数

根据第i个数选或者是不选转移

ans= Σ  2^j * 第j位的dp[n]

这里是平方和

设一个子集位运算后的结果为x,它对答案的贡献为x^2

把x按二进制拆为p位,即(x0+x1+x2+x_p-1)

其中xi表示2^i

那它对答案的贡献为 (x0+x1+x2+x_p-1)^ 2

去括号就是  x0*x0+x0*x1+……+x0*x_p-1+……+ x_p-1 * x0+x_p-1 * x1+…… x_p-1 * x_p-1

即 Σ Σ xi*xj    i,j ∈[0,p)

每一项至于两位有关

所以枚举任意两位a,b

dp[i][0/1][0/1]表示前i个数,第a位为0/1,第b位为0/1的方案数

ans= Σ Σ 2^(i+j) * 枚举的两位为i和j时的dp[n][1][1]

即dp求的是表达式中每一项的系数

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;

#define N 50001

const int mod=1e9+7;

int n,p;
int to[2][2];
int b[N];

int dp[N][2][2];

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-‘0‘; c=getchar(); }
}     

int get(int p,int q)
{
    memset(dp,0,sizeof(dp));
    bool pp,qq;
    for(int i=1;i<=n;++i)
    {
        pp=b[i]>>p&1;
        qq=b[i]>>q&1;
        dp[i][pp][qq]++;
        dp[i][pp][qq]-=dp[i][pp][qq]>=mod ? mod : 0;
        for(int j=0;j<2;++j)
            for(int k=0;k<2;++k)
            {
                dp[i][j][k]+=dp[i-1][j][k];
                dp[i][j][k]-=dp[i][j][k]>=mod ? mod : 0;
                dp[i][to[j][pp]][to[k][qq]]+=dp[i-1][j][k];
                dp[i][to[j][pp]][to[k][qq]]-=dp[i][to[j][pp]][to[k][qq]]>=mod ? mod : 0;
            }
    }
    return dp[n][1][1];
}

int main()
{
    read(n); read(p);
    for(int i=0;i<2;++i)
        for(int j=0;j<2;++j)
             read(to[i][j]);
    for(int i=1;i<=n;++i) read(b[i]);
    int ans=0;
    for(int i=0;i<p;++i)
        for(int j=0;j<p;++j)
        {
            ans+=(1LL<<i+j)%mod*(long long)get(i,j)%mod;
            ans-=ans>=mod ? mod : 0;
        }
    cout<<ans;
} 

1684 子集价值 

基准时间限制:5 秒 空间限制:131072 KB 分值: 80 难度:5级算法题

 收藏

 关注

lyk最近在研究位运算。

它发现除了xor,or,and外还有很多运算。

它新定义了一种运算符“#”。

具体地,可以由4个参数来表示。

ai,j表示

i#j。

其中i,j与a的值均∈[0,1]。

当然问题可以扩展为>1的情况,具体地,可以将两个数分解为p位,然后对于每一位执行上述的位运算,再将这个二进制串转化为十进制就可以了。

例如当 a0,0=a1,1=0,a0,1=a1,0=1时,3#4在p=3时等于7,2#3在p=4时等于1(实际上就是异或运算)。

现在lyk想知道的是,已知一个数列b。

它任意选取一个序列c,满足 c1<c2<...<ck,其中1≤c1且ck≤n ,这个序列的价值为 bc1 # bc2 #...# bck 的平方。

这里我们假设k是正整数,因此满足条件的c的序列一定是 2n−1 。lyk想知道所有满足条件的序列的价值总和是多少。

例如样例中,7个子集的价值分别为1,1,4,4,9,9,0。总和为28。

由于答案可能很大,只需对1,000,000,007取模即可。

Input

第一行两个整数n(1<=n<=50000),p(1<=p<=30)。
第二行4个数表示a0,0,a0,1,a1,0,a1,1。(这4个数都∈{0,1})
第三行n个数bi(0<=bi<2^p)。

Output

一行表示答案。

Input示例

3 30
0 1 1 0
1 2 3

Output示例

28

原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8454505.html

时间: 2024-10-20 05:18:16

51Nod 1684 子集价值 (平方和去括号技巧)的相关文章

批量重命名去括号

WINDOW处理数据集之后导出到文件夹里面,需要批量对数据集进行重命名.但是WINDOWS重命名之后的文件名都带括号,去括号的方式就是在数据集文件夹下新建一个txt文件,编辑内容为: @Echo Off&SetLocal ENABLEDELAYEDEXPANSION FOR %%a in (*) do ( set "name=%%a" set "name=!name: (=!" set "name=!name:)=!" ren "

提高程序员职场价值的10大技巧

如果你已经是个很牛叉的程序员,但是依然觉得觉得还不够的话,欢迎阅读此文.本文旨在帮助各位更上一层楼. 你是不是觉得自己已经掌握了所有的编程技巧?别太自以为是了! 会写代码的确很重要,但是要拿到更好薪水,则更依赖于别人是否知道你的才能.换言之,你需要推销自己.下面是如何成功推销的秘诀. 开发技巧No. 1:博客 建立自己的博客,每月至少发布一篇文章.做点研究,因为只有自己亲身经历过,才能言之有物,不会听上去像吹牛皮.学会如何写文章,像以前你的老师教的那样:列大纲,描述情节,最后检查语法和错别字.然

POJ1690 简单运算去括号

题目大意: 给定一串只含加减和括号的运算,去掉没用的括号和空白字符输出 这里其实只要去找当前括号前面那个运算符是不是减号,如果是减号且这个括号内出现过运算符说明这个括号应该存在 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 6 using namespace std; 7 #define N 1010 8 #define MOD

51NOD 1110 距离之和最小 V3(中位数 + 技巧)

传送门 X轴上有N个点,每个点除了包括一个位置数据X[i],还包括一个权值W[i].该点到其他点的带权距离 = 实际距离 * 权值.求X轴上一点使它到这N个点的带权距离之和最小,输出这个最小的带权距离之和. Input 第1行:点的数量N.(2 <= N <= 10000) 第2 - N + 1行:每行2个数,中间用空格分隔,分别是点的位置及权值.(-10^5 <= X[i] <= 10^5,1 <= W[i] <= 10^5) Output 输出最小的带权距离之和.

【模拟1561】[JSOI2009]去括号

#include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #define maxn 100001 using namespace std; char s[maxn]; bool w[maxn]; int S[maxn],n,top,tt,T; bool pd(int l,int

SCI科技论文的写作技巧-核心价值

第一次写SCI论文的撰写技巧,本身不是大牛,也许没什么资格谈这个.在此仅是个人的一些思考,对不对,好不好,且当另论. 对于偏向应用的工科生来说,写SCI论文不是一件简单的事情.当然,也不是没可能.全在于如何提取.构思.组织你的论文.论文本身的学术价值当然少不了.但对一个问题,在有的人眼里,就是"这么简单,有什么可写的":而对于另外一些人,却能挖掘出背后的深度.广度.和细度,完成一篇较高价值的论文发表.至于学术价值方面,在次就不赘述.主要谈一下如何来构思SCI的论文,简单概括就是四个字:

傻瓜方法求集合的全部子集问题(java版)

给定随意长度的一个集合.用一个数组表示,如{"a", "b","c"},求它的全部子集.结果是{ {a}, {b}, {c}, {a,b}, {a,c}, {b,c}, {a,b,c}}和一个空集. 以下讲的就是怎样用一个原始的傻瓜方法(非算法)求它的全部子集. 首先我们知道是它的子集个数是2^length,假设长度是3,那子集就共同拥有2的3次方=8个,包含空集. 求子集,我的做法是对不论什么一项做推断,有或者无,用1和0来相应表示. 那么像这

面试技巧与相关细节

人才应在面谈前做好充分准备 1.充分了解所谈职位的工作内容(JD很重要)工作环境以及该部门的组织架构以及所谈职位的位置2.可以网上查询该公司的具体情况包括产品/服务,规模,地点,品牌,优劣势等: 3.该公司主要的竞争对手或是主要客户群体:4.确定已经确认了面谈时间及确切地址,面试官的职位及全名尽可能知道他/她大概的背景/管理风格(负责顾问最好能有书面及口头的确认) 5.最好能在面谈之前花一点时间回顾一下你的简历或是你之前的经历尤其注重回忆你每一个曾经经历过的公司以及工作岗位并且整理在未来的面谈中

创业之前 ——《黑客与画家》作者最新文章

创业之前 Paul Graham 原文 2014年10月 (这篇文章是我在斯坦福大学举办的Sam Altman创业课堂上的嘉宾演讲稿.本意是写给大学生的,但其中的大部分内容也适合其它年龄的创业者.) 有孩子的一大好处是,当你给年轻人意见的时候,你会问自己,"如果是我的孩子的话,我要怎样告诉他?"我孩子还很小,但我可以想象我孩子上大学的时候,我会告诉他创业的哪些东西.然后这正也是我现在要告诉你的. 创业是很违背直觉的.我还不确定原因是什么.可能是创业的知识还没有渗透进社会文化.但不管什么