zoukankan      html  css  js  c++  java
  • 【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

    由于我们要求异或和 所以各个位不影响 不难想到 要转换成二进制做

    example1

    深蓝色的部分表示和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))

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 typedef long long ll;
     5 using namespace std;
     6 const ll N=20001,mo=1000000007;
     7 struct info{
     8     ll t,num,s;
     9     info(const ll a=0,const ll b=0,const ll c=0):
    10         t(a),num(b),s(c){}
    11 }im[N];
    12 struct inas{
    13     ll bo,x,y;
    14     inas(const ll a=0,const ll b=0,const ll c=0):
    15         bo(a),x(b),y(c){}
    16 }ask[N];
    17 ll n,m,f[N][13][2],sum[N][13],change[N];
    18 char ch;
    19 inline bool cmp(info a,info b){ return a.num<b.num; }
    20 void makechange(){
    21     sort(im+1,im+n+1,cmp);
    22     for (ll i=1;i<=n;i++) change[im[i].t]=i;
    23 }
    24 void push(ll x,ll y,ll z){
    25     ll now=im[x+1].s,nex=x+1,ney,nez,free;
    26     for (ll i=0;i<10;i++)
    27     if ((now>>i)&1){
    28         if (i<y) ney=y,nez=z^((now>>y)&1),free=i;
    29         if (i>y) ney=i,nez=sum[x][i],free=y;
    30         if (i==y) ney=i,nez=z,free=i;
    31         f[nex][ney][nez]=(f[nex][ney][nez]+(f[x][y][z]<<free)%mo)%mo;
    32     }
    33 }
    34 void makef(ll t){
    35     for (ll i=t-1;i<n;i++){
    36         for (ll j=0;j<10;j++){
    37             f[i+1][j][0]=f[i+1][j][1]=0;
    38             sum[i+1][j]=sum[i][j]^((im[i+1].s>>j)&1);
    39         }
    40         for (ll j=0;j<10;j++)
    41         for (ll k=0;k<=1;k++)
    42         if (f[i][j][k]) push(i,j,k);
    43     }
    44 }
    45 void print(ll t){
    46     ll res=0;
    47     for (ll i=9;i>=0;i--){
    48         res=(res+f[n][i][(t>>i)&1])%mo;
    49         if (sum[n][i]!=((t>>i)&1)) break;
    50     }
    51     printf("%I64d
    ",res);
    52 }
    53 int main(){
    54     scanf("%I64d%I64d",&n,&m);
    55     for (ll x,i=1;i<=n;i++){
    56         scanf("%I64d",&x);
    57         im[i]=info(i,0,x+1);
    58     }
    59     for (ll i=1,x,y;i<=m;i++){
    60         scanf("
    %c",&ch);
    61         if (ch=='Q'){
    62             scanf("%I64d",&x);
    63             ask[i]=inas(0,x,0);
    64         }else{
    65             scanf("%I64d%I64d",&x,&y);
    66             ask[i]=inas(1,x+1,y+1);
    67             ++im[x+1].num;
    68         }
    69     }
    70     makechange();
    71     f[0][0][0]=1;
    72     makef(1);
    73     for (ll i=1;i<=m;i++)
    74     if (ask[i].bo){
    75         ll now=change[ask[i].x];
    76         im[now].s=ask[i].y;
    77         makef(now);
    78     }else print(ask[i].x);
    79 }
    View Code
  • 相关阅读:
    高并发,执行耗时短的任务,还有低并发,执行耗时长的任务,各自选取什么样的线程池比较合理?为什么?如果业务场景是高并发,且任务耗时长时,有什么解决思路?
    java的重载、覆盖和隐藏的区别
    写出以下代码的输出结果?
    MySQL存储引擎通常有哪3种?各自分别有什么特点?应用场景是哪些?
    oracle的索引有几种?各有何用途?
    Apach Web Server区别于其他应用服务器的主要特点是什么?
    eclipse左边工程列表不见了,怎么调出来
    Java 生成一个记事本
    JS indexOf(),split(),substring(),substr(),Math.ceil(),Math.floor(),Math.round()的内容
    Java 有关于线程
  • 原文地址:https://www.cnblogs.com/g-word/p/3482932.html
Copyright © 2011-2022 走看看