51nod 1684 子集价值
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取模即可。
第一行两个整数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)。
一行表示答案。
3 30
0 1 1 0
1 2 3
28
分析:挺好的一道题.
先想想问题的简化版:不是求平方和,而是求和该怎么做. 肯定是不能枚举子集进行统计的. 二进制上的每一位都是独立的,如果是求最值,可以从高位到低位依次考虑,如果是求和,可以求出每一位是1的方案数,如果第i位为1,那么它对答案的贡献就是2^i * 第i位为1的方案数.
另f[i][0/1]表示前i个数中,当前枚举的第j位为1的方案数.每个数都有选和不选两种选择. 最后的答案就是Σf[n][1] * 2^j
如果是求平方和怎么办呢?(a1 + a2 + a3 +...... + an) ^ 2拆开来可以得到:a1 ^ 2 + a2 ^ 2 + a3 ^ 3 + ...... + an^2 + 2a1a2 + 2a1a3 + ...... + 2a1an + ...... + an-1an.每一项都与两位有关. 那么可以枚举两位j,k,求使得第j位和第k位都为1的方案数,它对答案的贡献就是2^(j+k) * 方案数,状态就要表示为f[i][0/1][0/1]了.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; typedef long long ll;
const ll mod = 1e9+,maxn = ;
ll n,p,a[][],b[maxn],f[maxn][][],ans; void Mod(ll &x)
{
if (x >= mod)
x -= mod;
} ll solve(ll x,ll y)
{
memset(f,,sizeof(f));
for (ll i = ; i <= n; i++)
{
ll t1 = (b[i] >> x) & ;
ll t2 = (b[i] >> y) & ;
f[i][t1][t2]++;
Mod(f[i][t1][t2]);
}
for (ll i = ; i <= n; i++)
{
ll t1 = (b[i] >> x) & ;
ll t2 = (b[i] >> y) & ;
for (ll j = ; j <= ; j++)
for (ll k = ; k <= ; k++)
{
f[i][j][k] += f[i - ][j][k];
Mod(f[i][j][k]);
f[i][a[j][t1]][a[k][t2]] += f[i - ][j][k];
Mod(f[i][a[j][t1]][a[k][t2]]);
}
}
return f[n][][];
} int main()
{
scanf("%lld%lld",&n,&p);
for (ll i = ; i <= ; i++)
for (ll j = ; j <= ; j++)
scanf("%lld",&a[i][j]);
for (ll i = ; i <= n; i++)
scanf("%lld",&b[i]);
for (ll i = ; i < p; i++)
for (ll j = ; j < p; j++)
{
ll temp = (1LL << (i + j)) % mod * solve(i,j) % mod;
ans += temp;
Mod(ans);
}
printf("%lld\n",ans); return ;
}
51nod 1684 子集价值的更多相关文章
- 51Nod 1684 子集价值 (平方和去括号技巧)
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1684 题意: 新建一个位运算,求所有子集通过这个位运算后的答案的平方和是 ...
- [51nod1684]子集价值
lyk最近在研究位运算. 它发现除了xor,or,and外还有很多运算. 它新定义了一种运算符"#". 具体地,可以由4个参数来表示. ai,j表示 i#j. 其中i,j与a的值均 ...
- 51NOD 区间的价值 V2
http://www.51nod.com/contest/problem.html#!problemId=1674 因为题目要求的只是& 和 | 这两个运算.而这两个运算产生的值是有限的. & ...
- 51nod 1564 区间的价值 | 分治 尺取法
51nod 1564 区间的价值 题面 一个区间的价值是区间最大值×区间最小值.给出一个序列\(a\), 求出其中所有长度为k的子区间的最大价值.对于\(k = 1, 2, ..., n\)输出答案. ...
- 【51Nod 1674】【算法马拉松 19A】区间的价值 V2
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1674 对区间分治,统计\([l,r]\)中经过mid的区间的答案. 我的 ...
- 【51nod】1564 区间的价值
题解 这个要注意到一个长度大的区间的最大价值一定比长度小的区间的价值要大 然后我们以每个点为最小值,显然区间越长最大值越大,然后我们更新最大区间长度的取值,这个可以用单调栈求这个最小值能更新到的左右端 ...
- 51nod 1674 区间的价值V2(思维+拆位+尺取法)
最近被四区题暴虐... 题意:lyk拥有一个区间. 它规定一个区间的价值为这个区间中所有数and起来的值与这个区间所有数or起来的值的乘积. 例如3个数2,3,6.它们and起来的值为2,or起来的值 ...
- 【51Nod 1616】【算法马拉松 19B】最小集合
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1616 这道题主要是查询一个数是不是原有集合的一个子集的所有数的gcd. ...
- 51nod 1622 集合对[算法马拉松19 C]
题目链接:https://www.51nod.com/contest/problem.html#!problemId=1622 第一次参加算法马拉松,我就是去看大神们疯狂秒题,然后感受绝望的orz.. ...
随机推荐
- 如何使用Win+R快捷键打开自定义程序
鉴于大家对于提高效率这块有争议,更改了下标题. 大家平时一定都使用过Win+R运行快捷键, 在运行里可以快捷的打开一些系统软件,比如说输入mstsc是打开远程连接,输入explorer是打开文件管理器 ...
- Python os.makedirs() 方法
os.makedirs() 方法用于递归创建目录.像 mkdir(), 但创建的所有intermediate-level文件夹需要包含子目录. 语法 makedirs()方法语法格式如下: os.ma ...
- request.quest/query_string/params/body等方法介绍
假设url:http://192.168.1.111:8080/api/cluster/group?wzd=111&abc=cc 方法类型:POST,body是{"name" ...
- MySql 8 命令
1-创建用户 create user 用户名@'%' identified by '密码'; create user 用户名@'localhost' identified by '密码'; 2-授 ...
- 陈爽 软件工程导论week2.1
软件工程导论week2.1 第一章概论问题:1.程序=算法+数据结构 软件=程序+软件工程软件工程的目标是创造足够好的软件,可以从用户满意度,可靠性,软件流程的质量,可维护性等方面判断,但是我们没有 ...
- 6/3 sprint2 看板和燃尽图的更新
- jenkin重新注册用户
http://www.cnblogs.com/xiao-fy/
- jquery mobiscroll 滑动、滚动
mobiscroll : 滑动选择 2.13.2版本免费,官网(mobiscroll.com)收费 先从官方下载2.13.2体验版下来,查看例子结合官方API学习( http://docs.mobis ...
- 内存测试——Android Studio中对应进程的Heap
通过Android Studio的Heap查看该程序的目前占用内存大小,多次进出界面,观察内存内存大小的变化.用Heap监测应用进程使用内存情况的步骤如下: 1. 启动Android Studio—& ...
- HDU4678_Mine
很有意思,很好的题目. 这样的,一个n*m的扫雷地图,告诉你哪些地方是有雷的.一个人如果点在了空白处,那么与其相邻的(八个方向)的数字以及空白都会递归地显示出来,如果点在数字上面,那么就只会显示这一个 ...