zoukankan      html  css  js  c++  java
  • CF1245F: Daniel and Spring Cleaning

    CF1245F: Daniel and Spring Cleaning

    题意描述:

    • 给定区间([L,R]),其中 ((0leq L,Rleq 10^9)),问在区间内有多少数对((x,y))满足(x+y==xland y)

    输入描述:

    • 第一行输入一个(T)表示测试样例数目。
    • 接下来每一个测试样例输入两个整数(L,R)表示区间。

    输出描述:

    • 输出一个整数表示答案。

    思路:

    • 首先对条件进行变形。
    • (x+y==xland y),有(x&y==0),证明略。
    • 那么题目要求的就转化为区间内(x&y==0)的数对数量。
    • 定义(f(l,r))([l,r))区间内满足条件的数对的数量。那么显然有(f(0,r)=2r+f(1,r)),因为(0)可以和任意数字组合。
    • 性质:(f(2l,2r)=3f(l,r))
      • 证明:
      • 考虑满足条件的数对((x,y))的二进制表示。对于最右边的位置,有三种选择方式((0,1),(1,0),(0,0))
      • 选择其他位的方法是(f(l,r)),因此(f(2l,2r)=3f(l,r))
    • 这样我们可以每次对范围除以(2),但这样就要保证我们的(l,r)是偶数,当他不是偶数的时候可以进行如下操作。
    • 定义(g(x,n))为满足以下条件的(y)的个数。
      • (0leq y<n)
      • (x&y==0)
    • 那么当(l)是奇数的时候:
      • (f(l+1,r)=f(l,r)-2(g(l,r)-g(l,l)))
        • 解释:由最上方定义的那个性质可以知道:(f(l,r)=num+f(l+1,r)),其中(num)(l)([l,r])区间内的数满足条件的数对((l,x))数量((xin[l,r]))
        • 那么由(g(i,j))的定义可知,(g(l,r))表示(l)([0,r])范围内满足条件的(y)的个数,(g(l,l))表示在([0,l))范围内满足条件的(y)的个数,那么两个相减就是([l,r))区间内满足条件数对的数量。当然要(*2),因为((x,y))((y,x))为两种情况。
      • 变形为(f(l,r)=f(l+1,r)+2(g(l,r)-g(l,l)))
    • 同样的当(r)为奇数的时候有:
      • (f(l,r-1)=f(l,r)-2(g(r-1,r)-g(r-1,l)))
        • 解释:他的差值也就是(r-1)([l,r))内有多少满足条件的数对。
      • (f(l,r)=f(l,r-1)+2(g(r-1,r)-g(r-1,l)))
    • 于是我们只需要考虑如何快速的计算(g(i,j))
    • 定义(h(x,n))为满足下列条件的(y)的数量。
      • (n-lowbit(n)leq y<n)
      • (x& y==0)
    • 那么有(g(x,n)=h(x,n)+g(x,n-lowbit(n))(n>0))
    • 对于(h(x,n)),我们可以在(logn)的时间内计算出来。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    ll g(int a, int b)
    {
        ll res = 0;
        ll num = 0;
    
        for(int i = 1; i <= b; i <<= 1)
        {
            if(b & i)
            {
                b ^= i;
                if(!(a&b)) res += 1<<num;
            }
            if(!(a&i)) num++;
        }
    
        return res;
    }
    
    ll calc(int a, int b)
    {
        if(a == b) return 0;
        if(a == 0) return 2*b - 1 + calc(1, b);
        ll res = 0;
        if(a & 1)
        {
            //f(l,r)=f(l+1,r)+2(g(l,r)-g(l,l))
            res += 2 * (g(a, b) - g(a,a));
            a++;
        }
        if(b & 1)
        {
            //f(l,r)=f(l,r-1)+2(g(r-1,r)-g(r-1,l))
            res += 2 * (g(b-1, b) - g(b-1, a));
            b--;
        }
        return res + 3 * calc(a/2, b/2);
    }
    
    int main()
    {
        int T; cin >> T;
        int a, b;
        while(T--)
        {
            cin >> a >> b;
            cout << calc(a, b+1) << endl;
        }
        return 0;
    }
    
    
  • 相关阅读:
    jQuery 语法
    jQuery 简介
    把数据存储到 XML 文件
    XML 注意事项
    XML DOM (Document Object Model) 定义了访问和操作 XML 文档的标准方法。
    通过 PHP 生成 XML
    XML 命名空间(XML Namespaces)
    XML to HTML
    XMLHttpRequest 对象
    使用 XSLT 显示 XML
  • 原文地址:https://www.cnblogs.com/zxytxdy/p/11780430.html
Copyright © 2011-2022 走看看