【FOI】异或问题
题意:
给出n个数ai 和m个操作 操作有两种
C x y:将ax的值改为y
Q x:求几种方案使得 b1^b2^...^bn=x(ai>=bi)
题解:
先推荐一个不错的题解 题目差不多 我之前就是看着题解做的
http://hi.baidu.com/billdu/item/c749952ab2ab50c2ef10f137
首先我们先不考虑修改 即给你n个数ai 求几种方案使得异或和为x
为了方便起见 我们将原题的条件修改为0≤bi<ai 也就是原来的a数列中每一项都加1
由于我们要求异或和 所以各个位不影响 不难想到 要转换成二进制做
深蓝色的部分表示和ai的这一位一样
绿色部分表示ai的这一位是1 而这里是0的一位
橘黄色的部分表示不可以被随便确定的位 我们称其为“控制位”
而浅蓝色部分表示可以被随便确定的位
这种情况可能成为解的充要条件是没有橘黄色格子的列中的数异或起来和答案的这几位一样 答案显然是2^(浅蓝色格子数)
状态表示:
f[i][j][k]表示前i个数 1到j-1位有"控制位" 且第j位的异或和为k的方案数(这里的第一位是指最右边的一位)
转移:
为了方便 我们用递推的方法实现转移
对于 f[i][j][k] 枚举l 表示要将第i+1个数的第l位的1转换为0
令xo[i][j]表示前i个数第j位的异或和
当 l<j:nei=i+1,nej=j,nez=k^(第i+1个数的第j位),free=l-1
当 l==j:nei=i+1,nej=j,nez=k,free=l-1
当 l>j:nei=i+1,nej=l,nez=xo[i][l],free=j-1
f[nei][nej][nek]+=f[i][j][k]<<free
统计答案:
上面提到 一种状态成为解的充要条件是没有橘黄色格子的列中的数异或起来和答案的这几位一样
我们累加f[n][i][x的第i位] 直到xo[n][i-1]不等于x的第i-1位
修改:
用上面的方法每次修改都要把f数组重建 有1000次修改 每次O(n*log^2(1000)) 显然会tle
AK想到了一种机智的方法:
把可能变化的数放在数组的最后面 那么每次修改就最多只会影响后面的1000位
总的时间复杂度就大概是O(1000^2*log^2(1000))
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
typedef long long ll;
using namespace std;
const ll N=,mo=;
struct info{
ll t,num,s;
info(const ll a=,const ll b=,const ll c=):
t(a),num(b),s(c){}
}im[N];
struct inas{
ll bo,x,y;
inas(const ll a=,const ll b=,const ll c=):
bo(a),x(b),y(c){}
}ask[N];
ll n,m,f[N][][],sum[N][],change[N];
char ch;
inline bool cmp(info a,info b){ return a.num<b.num; }
void makechange(){
sort(im+,im+n+,cmp);
for (ll i=;i<=n;i++) change[im[i].t]=i;
}
void push(ll x,ll y,ll z){
ll now=im[x+].s,nex=x+,ney,nez,free;
for (ll i=;i<;i++)
if ((now>>i)&){
if (i<y) ney=y,nez=z^((now>>y)&),free=i;
if (i>y) ney=i,nez=sum[x][i],free=y;
if (i==y) ney=i,nez=z,free=i;
f[nex][ney][nez]=(f[nex][ney][nez]+(f[x][y][z]<<free)%mo)%mo;
}
}
void makef(ll t){
for (ll i=t-;i<n;i++){
for (ll j=;j<;j++){
f[i+][j][]=f[i+][j][]=;
sum[i+][j]=sum[i][j]^((im[i+].s>>j)&);
}
for (ll j=;j<;j++)
for (ll k=;k<=;k++)
if (f[i][j][k]) push(i,j,k);
}
}
void print(ll t){
ll res=;
for (ll i=;i>=;i--){
res=(res+f[n][i][(t>>i)&])%mo;
if (sum[n][i]!=((t>>i)&)) break;
}
printf("%I64d\n",res);
}
int main(){
scanf("%I64d%I64d",&n,&m);
for (ll x,i=;i<=n;i++){
scanf("%I64d",&x);
im[i]=info(i,,x+);
}
for (ll i=,x,y;i<=m;i++){
scanf("\n%c",&ch);
if (ch=='Q'){
scanf("%I64d",&x);
ask[i]=inas(,x,);
}else{
scanf("%I64d%I64d",&x,&y);
ask[i]=inas(,x+,y+);
++im[x+].num;
}
}
makechange();
f[][][]=;
makef();
for (ll i=;i<=m;i++)
if (ask[i].bo){
ll now=change[ask[i].x];
im[now].s=ask[i].y;
makef(now);
}else print(ask[i].x);
}
【FOI】异或问题的更多相关文章
- Android数据加密之异或加密算法
前言: 这几天被公司临时拉到去做Android IM即时通信协议实现,大致看了下他们定的协议,由于之前没有参与,据说因服务器性能限制,只达成非明文传递,具体原因我不太清楚,不过这里用的加密方式是采用异 ...
- Oracle数据库异机升级
环境: A机:RHEL5.5 + Oracle 10.2.0.4 B机:RHEL5.5 需求: A机10.2.0.4数据库,在B机升级到11.2.0.4,应用最新PSU补丁程序. 目录: 一. 确认是 ...
- [LeetCode] Maximum XOR of Two Numbers in an Array 数组中异或值最大的两个数字
Given a non-empty array of numbers, a0, a1, a2, … , an-1, where 0 ≤ ai < 231. Find the maximum re ...
- [PHP][位转换积累]之异或运算的简单加密应用
异或的符号是^.按位异或运算, 对等长二进制模式按位或二进制数的每一位执行逻辑按位异或操作. 操作的结果是如果某位不同则该位为1, 否则该位为0. xor运算的逆运算是它本身,也就是说两次异或同一个数 ...
- Poj The xor-longest Path 经典题 Trie求n个数中任意两个异或最大值
Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 5646 Accepted: 1226 Description In an ...
- RMAN异机恢复遭遇ORA-01547、ORA-01152、ORA-01110错误案例
测试环境: 操作系统 : Red Hat Enterprise Linux ES release 4 (Nahant Update 4) VMWARE 数据库 : O ...
- RAC异机恢复
RAC异机恢复PDCL到PFCL: PNCL:RAC+ASM ,product env db name:PNCL instance:PDCL1 PDCL2 PFCL:RAC+ASM ,perf ...
- BZOJ 3261: 最大异或和
Description 一个序列,支持两个操作. 1.在序列尾加入一个数. 2.询问 [l,r] 中与 x 异或值最大的数. \(n\leqslant 3*10^5\) Sol 可持久化 Trie 树 ...
- 异或之(bzoj 3689)
Description 给定n个非负整数A[1], A[2], --, A[n].对于每对(i, j)满足1 <= i < j <= n,得到一个新的数A[i] xor A[j],这 ...
随机推荐
- 【C++基础】关键字static 局部变量
1.局部变量 static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值: int test(int j){ static int i=10; i=i+j ...
- Python:使用threading模块实现多线程编程
转:http://blog.csdn.net/bravezhe/article/details/8585437 Python:使用threading模块实现多线程编程一[综述] Python这门解释性 ...
- Android 图片旋转(使用Matrix.setRotate方法)
imageView2 = (ImageView) findViewById(R.id.img2); Bitmap bitmap = BitmapFactory.decodeResource(getRe ...
- MySQL在windows和linux下的表名大小写问题
MySQL在windows下是不区分大小写的,将script文件导入MySQL后表名也会自动转化为小写,结果再想要将数据库导出放到linux服务 器中使用时就出错了.因为在linux下表名区分大小写而 ...
- 李洪强iOS开发之【零基础学习iOS开发】【02-C语言】07-基本数据类型
C语言有丰富的数据类型,因此它很适合用来编写数据库,如DB2.Oracle等大型数据库都是C语言写的.其中,提供了4种最常用的基本数据类型:char.int.float.double,使用这些数据类型 ...
- Java中JSON的简单使用与前端解析
http://www.blogjava.net/qileilove/archive/2014/06/13/414694.html 一.JSON JSON(JavaScript Object Notat ...
- 如何快速查看linux的发行版信息
思路一: 在CentOS中想查看发行版信息,输入了lsb_release -a 命令却报错了,通过输入以下命令进行安装 yum install redhat-lsb -y 然后继续查看发行版信息 [r ...
- EPEL库安装
EPEL是yum的一个软件源,里面包含了许多基本源里没有的软件了,但在我们在使用epel时是需要安装它才可以了.EPEL,即Extra Packages for Enterprise Linux的简称 ...
- SQL Server常见问题总结
写在前面 在QQ群,微信群,论坛中经常帮助使用SQL Server数据库的朋友解决问题,但是有一些最常见最基本的问题,每天都有人问,回答多了也不想再解答了,索性把这些问题整理一下,再有人问到直接发链接 ...
- WinCE NAND flash - FAL
http://blog.csdn.net/renpine/article/details/4572347 http://msdn.microsoft.com/en-US/library/ee48203 ...