题目大意
给定一个区间,构造一个单调不减的序列,使得其前缀异或和与后缀异或和均单调递减,判断这种序列是否存在并输出任意一种解。
思路
暴力 dfs 当然会 TLE,所以我们要仔细分析:
① 在什么情况下异或和能够单调不减?
分析样例,将数字转化成二进制,就是下图:
 
 发现没,其实这种序列都有一个特征:每一位二进制位都恰好对应一个数字。这也是这道题的核心。
 类似的,我们还可以构造许多这样的序列,比如 3(011),4(100),8(1000),16(10000)。
② 在什么情况下问题有解?
在考虑这个问题之前,首先我们思考:在这样的序列中最后一个元素的最小值是多少?
 按照之前的规律,每一位二进制位都恰好对应一个数字,这样我们就可以把第 1 个二进制位给第 1 个数字,第 2 个二进制位给第 2 个数字……直到第 n 个二进制位,给第 n 个数字。发觉没,这些数字不正是 2 的整数幂吗?这个序列 f 的通项公式为:
 
    
     
      
       
        f
       
       
        (
       
       
        i
       
       
        )
       
       
        =
       
       
        
         2
        
        
         
          i
         
         
          −
         
         
          1
         
        
       
       
        (
       
       
        1
       
       
        ≤
       
       
        i
       
       
        ≤
       
       
        n
       
       
        )
       
      
      
       f(i) = 2^{i-1} (1 \le i \le n)
      
     
    f(i)=2i−1(1≤i≤n)
 接下来前面的问题就迎刃而解了,我们只需要判断 
    
     
      
       
        
         
          log
         
         
          
         
        
        
         2
        
       
       
        m
       
       
        +
       
       
        1
       
      
      
       \log_2m + 1
      
     
    log2m+1 是否小于 n,如果小于 n 就无解,否则就将上述序列输出即可。
完整代码
温馨提示:抄袭不是一个好习惯哦~
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n, t, m;
signed main() {
    scanf("%d", &t);
    while(t--) {
    	scanf("%lld%lld", &n, &m);
    	if(log2(m)+1 < n) {puts("No"); continue;}
    	puts("Yes");
    	for(long long i = 1;i < pow(2, n);i *= 2) printf("%lld ", i);
    	puts(""); 
    }
    return 0;
}
summary
这是一道对数学运算的深度理解与灵活运用题



















