CF1391-Codeforces Round #663 (Div. 2)-A. Suborrays【抽屉原理】

题目链接
题意:找出正整数n的一个排列 p p p,使得其为满足以下条件的序列

  • ( p i  OR  p i + 1  OR  …  OR  p j − 1  OR  p j ) ≥ j − i + 1 (p_i \text{ OR } p_{i+1} \text{ OR } \ldots \text{ OR } p_{j-1} \text{ OR } p_{j}) \ge j-i+1 (pi OR pi+1 OR  OR pj1 OR pj)ji+1 ( 1 ≤ i ≤ j ≤ n ) (1 \le i \le j \le n) 1ijn
    也就是每个子序列的按位或之和不小于其中元素的数量。
    思路:先说结论:输出任意一个排列即可
    我们不难发现以下事实:对于任意一组数字,其按位或之和必然不小于其中的最大值,即:
    ( p i  OR  p i + 1  OR  …  OR  p j − 1  OR  p j ) ≥ m a x { p i , p i + 1 , . . . , p j } (p_i \text{ OR } p_{i+1} \text{ OR } \ldots \text{ OR } p_{j-1} \text{ OR } p_{j}) \ge max\{p_i,p_{i+1},...,p_j\} (pi OR pi+1 OR  OR pj1 OR pj)max{pi,pi+1,...,pj}
    所以只需子序列中元素的最大值大于等于其长度即可,假设:子序列长度为 n n n,最大元素小于n。那么我们有 n n n个元素的范围都在 [ 1 , n − 1 ] [1,n-1] [1,n1]内,根据抽屉原理,必然有两者相同,这与题目给定的 p p p是排列的条件矛盾,所以任意的排列都满足题意。
    AC代码:
#include 

#define ll long long
using namespace std;

int main() {
    ios::sync_with_stdio(0);
    ll t, n;
    cin >> t;
    while (t--) {
        cin>>n;
        for(int i=n;i>=1;i--) cout<<i<<' ';cout<<endl;
    }
    return 0;
}

你可能感兴趣的:(codeforces,算法)