【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],这 ...
随机推荐
- POJ-1088 滑雪 (包含部分自用测试数据)
这题最简单的想法是深搜+记录,由于数据量比较小.这么做可以AC.如果在h大的情况下这种递归方法总会有一些问题. 如果转换一下,这个可以使用递推来解决,先对高度进行由低到高的排序,然后顺序对这些高度计算 ...
- 如何在eclipse里使用git
新版都自带git插件了.在项目上右键,选team,选share project,再选择git就可以了. 如果在本地使用git比较简单.如果要多人共享的使用git,那么需要专门的服务器,并提供ssh,这 ...
- 【BZOJ 1046】 1046: [HAOI2007]上升序列
1046: [HAOI2007]上升序列 Description 对于一个给定的S={a1,a2,a3,-,an},若有P={ax1,ax2,ax3,-,axm},满足(x1 < x2 < ...
- linux编译注解
Linux kernel release 3.x <http://kernel.org/> These are the release notes for Linux version 3. ...
- 存储过程 务的概念 事务的特性 关于异常的处理 连接池 构JdbcUtil类
1 存储过程 1)用当地数据库语言,写的一段业务逻辑算法,并该算法存储在客户端 2)使用存储过程需要用于CallableStatement接口,同时需要使如下SQL命令调用:{call a ...
- Descending Order
Descending Order Description: Your task is to make a function that can take any non-negative integer ...
- oh my zsh命令
打开某个文件夹地址,输入 cdf 命令,会自动进入这个文件夹命令行 open ./ 打开当前命令行所在目录的文件夹
- 通过ngx-lua来统计Nginx上的虚拟主机性能数据
Web server调研分析 Filed under: Web Server — cmpan @ 2012-10-29 20:38:34 摘要 简单可依赖的架构首先需要有一个简单可依赖的前端WebSe ...
- Archlinux里面安装VMware Tools
用虚拟机学习linux确实很方便,但是和主机的文件共享是个大问题,VMWARE TOOLS可以很好的解决这个问题,但是在ARCH里却不能向大多数linux那样方便的安装,在查了很多帖子试了无数遍之后, ...
- WCF 服务调用RFC 出现异常
我在VS2010的WCF项目用connecter 3.0 调用 RFC 运行到 IDestinationConfiguration ID = new SAPConfig(); ...