zoukankan      html  css  js  c++  java
  • 洛谷3794 签到题IV

    题目描述

    给定一个长度为n的序列$a_1,a_2...a_n$,其中每个数都是正整数。

    你需要找出有多少对(i,j),$1 leq i leq j leq n$且$gcd(a_i,a_{i+1}...a_j)~xor~(a_i~or~a_{i+1}~or~...~or~a_j)=k$,其中xor表示二进制异或,or表示二进制或。
    输入输出格式
    输入格式:

    第一行两个整数n、k。

    第二行n个整数$a_1,a_2...a_n$。

    输出格式:

    输出合法的(i,j)的对数。

    输入输出样例
    输入样例#1: 复制

    5 6
    2 4 3 4 2

    输出样例#1: 复制

    8
    说明
    对于30%的数据,$n leq 500$。
    对于60%的数据,$n leq 100000$。
    对于100%的数据,$1 leq n,a_i leq 500000$。

    先枚举左端点,显然随着右端点右移,gcd不会增加,or不会减小

    而且gcd每次减小最大为原来1/2,所以相同的gcd共可以分成logn块,实际上远远达不到

    还有一个性质a^b^a=b

    所以gcd^or^gcd=k^gcd=or

    这样对于gcd相同的区间,用二分求出符合条件的or数量

    用ST表维护x~y的gcd和or,而且了log要预处理,这样会快一些

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 typedef long long lol;
     8 int GCD[500001][21],OR[500001][21],Log[500001],n,k;
     9 lol ans;
    10 int gcd(int a,int b)
    11 {
    12   if (!b) return a;
    13   return gcd(b,a%b);
    14 }
    15 int getg(int x,int y)
    16 {
    17   int d=Log[(y-x+1)];
    18   return gcd(GCD[x][d],GCD[y-(1<<d)+1][d]);
    19 }
    20 int getor(int x,int y)
    21 {
    22   int d=Log[(y-x+1)];
    23   return OR[x][d]|OR[y-(1<<d)+1][d];
    24 }
    25 int find(int x,int l,int g)
    26 {
    27   int r=n,as=l;
    28   while (l<=r)
    29     {
    30       int mid=(l+r)/2;
    31       int G=getg(x,mid);
    32       if (G==g) as=mid,l=mid+1;
    33       else r=mid-1;
    34     }
    35   return as;
    36 }
    37 void query(int d,int x,int l,int r)
    38 {
    39   int L=l,R=r,as1=0,as2=-1;
    40   while (l<=r)
    41     {
    42       int mid=(l+r)/2;
    43       int o=getor(x,mid);
    44       if (o==d) as1=mid,r=mid-1;
    45       if (o<d) l=mid+1;
    46       if (o>d) r=mid-1;
    47     }
    48     while (L<=R)
    49     {
    50       int mid=(L+R)/2;
    51       int o=getor(x,mid);
    52       if (o==d) as2=mid,L=mid+1;
    53       if (o<d) L=mid+1;
    54       if (o>d) R=mid-1;
    55     }
    56     ans+=as2-as1+1;
    57 }
    58 int main()
    59 {int i,x,pos,j;
    60   cin>>n>>k;
    61   for (i=1;i<=n;i++)
    62     {
    63       scanf("%d",&x);
    64       GCD[i][0]=x;
    65       OR[i][0]=x;
    66     }
    67   for (i=2;i<=n;i++)
    68     Log[i]=Log[i/2]+1;
    69   for (i=1;i<=20;i++)
    70     {
    71       for (j=1;j<=n;j++)
    72     if (j+(1<<i)-1<=n)
    73       {
    74         GCD[j][i]=gcd(GCD[j][i-1],GCD[j+(1<<i-1)][i-1]);
    75         OR[j][i]=OR[j][i-1]|OR[j+(1<<i-1)][i-1];
    76       }
    77     }
    78   for (i=1;i<=n;i++)
    79     {
    80       for (j=i;j<=n;j=pos+1)
    81     {
    82       int g=getg(i,j);
    83       pos=find(i,j,g);
    84       query(g^k,i,j,pos);
    85     }
    86     }
    87   cout<<ans;
    88 }
  • 相关阅读:
    xUtils
    android各类开发框架汇总
    The connection to adb is down, and a severe error has occured.问题解决
    android系统自带主题和自定义主题
    gson处理json和java对象互转
    android解析json数据
    andrid源码目录分析
    JavaScript学习笔记(1)字符串方法
    0day学习笔记(3)Windows定位API引起的惨案(原理)
    内存分页
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8359745.html
Copyright © 2011-2022 走看看