• 题解 codeforces 1457-D Xor-gun


    传送门


    【题意】

    初始给定长度为 (n),非递减的序列 ({a_n}) 。你可以进行操作,每次操作将两个相邻的数字消除,换为它们的异或和。问最少需要多少步使得原序列不再非递减。


    【分析】

    由于 (a_ileq 10^9)(2^{29}<10^9<2^{30})

    故根据抽屉原理,当数量 (ngeq 2 imes 30+1=61) 时,至少存在一个位数,使得以该位数为最高位的数字存在至少 (3) 个,且这 (3) 个数连续。

    设上述的其中一组 (3) 个数在序列中位置分别为 (a_{pos}, a_{pos+1}, a_{pos+2})

    (a_{pos+1}otimes a_{pos+2}) 的原最高位被异或消除,必定小于 (a_{pos}) ,则直接打破了非递减性。

    因此,当 (ngeq 61) 时,答案为 (1)

    (nleq 60) 时,采用随机化的方式,取步数最少解。

    当不存在该解时,直接输出 (-1)


    【代码】

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<ll, ll> pii;
    typedef double db;
    #define fi first
    #define se second
    const int MAXN=1e5+10;
    int n, a[MAXN], b[MAXN];
    int main(){
        ios::sync_with_stdio(0);
        cin.tie(0); cout.tie(0);
        clock_t start = clock();
        cin>>n;
        for(int i=1;i<=n;++i) cin>>a[i];
        if(n>60)
            cout<<1;
        else{
            int ans=0;
            do{
                memcpy(b+1, a+1, sizeof(a[0])*n);
                int len=n;
                while(len>1){
                    for(int i=1;i<len;++i)
                        if(b[i]>b[i+1]){
                            ans=max(ans, len);
                            break;
                        }
                    --len;
                    int pos=rand()%len+1;
                    b[pos]^=b[pos+1];
                    for(int i=pos+1;i<=len;++i)
                        b[i]=b[i+1];
                }
            }while( clock()-start<=1980 );
            if(ans) cout<<n-ans;
            else cout<<-1;
        }
        cout.flush();
        return 0;
    }
    
  • 相关阅读:
    误区30日谈25-30
    误区30日谈21-24
    误区30日谈16-20
    误区30日谈11-15
    误区30日谈6-10
    eclipse如何导入java项目文件
    Spring配置bean文件的底层实现方式
    hibernate中get,load,list,iterate的用法及比较
    MySQL数据库的事务管理
    单元格样式
  • 原文地址:https://www.cnblogs.com/JustinRochester/p/14920559.html
Copyright © 2020-2023  润新知