A. Make It Zero

题意:给定一个数组a,你要将所有元素都变为0,你有这样一个操作,选择L,R,将$i∈[l,r]$中的ai所有元素都变为L到R的ai的异或和,最多操作8次,问一个符合条件的操作流程是什么

思路:当是偶数时,我们可以选择L=1,R=N,操作两次即可,当是偶数时,我们先操作1到N-1,然后再操作最后一个数字即可

diamond:

#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
    int n;
    cin>>n;
    vector<int>q(n+1);
    int g=0;
    for (int i = 1; i <=n ; ++i) {
        cin>>q[i];
        g^=q[i];
    }
    vector<pair<int,int>>ans;
    if(n&1){
        ans.push_back({1,n-1});
        ans.push_back({1,n-1});
        ans.push_back({n-1,n});
        ans.push_back({n-1,n});
    }
    else{
        ans.push_back({1,n});
        ans.push_back({1,n});
    }
    cout<<ans.size()<<endl;
    for (auto i:ans) {
        cout<<i.first<<' '<<i.second<<endl;
    }

}
signed main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while (t--){
        solve();
    }
}

B. 2D Traveling

题意:有n个城市,编号从1到n,前k个城市是主要城市,坐标为$(xi,yi)$;你从x到y城市,如果x和y城市都是主要城市,那么无需成本,其他情况下,费用是x到y的曼哈顿距离,问从起点城市st到终点城市ed,最少花费是多少

思路:我们只需找出st到主要城市的最小值和ed到主要城市的最小值,然后这两个值相加与st到ed的曼哈顿距离取最小即可

diamond:

#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
    int n,k,a,b;
    cin>>n>>k>>a>>b;
    vector<pair<int,int>>q(n+1);
    for (int i =1; i <=n ; ++i) {
        cin>>q[i].first>>q[i].second;
    }
    auto [x,y]=q[a];
    auto [xx,yy]=q[b];
    int ans=abs(x-xx)+abs(y-yy);
    int s1=1e18;
    int s2=1e18;
    for (int i = 1; i <=k ; ++i) {
        s1=min(s1,abs(x-q[i].first)+abs(y-q[i].second));
        s2=min(s2,abs(xx-q[i].first)+abs(yy-q[i].second));
    }
    ans=min(s1+s2,ans);
    cout<<ans<<endl;

}
signed main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while (t--){
        solve();
    }

}

C. Fill in the Matrix

题意:给两个数n和m,要求构造一个n * m的矩阵,要求每一行都是一个排列,且每一列的MEX构成的数组S,要求MEX(s)最大。

思路:构造题.

不难发现发现当n<m时,MEX最大就是n+1,我们可以考虑这样构造,假设n=3,m=5

  • 0 1 2 3 4
  • 1 2 3 4 0
  • 2 3 4 0 1

    那么我们得到的S就是3 0 0 1 2,答案就是4

    当n>=m时,由于数字只有0到m-1,那么答案最大也就是m,考虑这样构造,假设n=6,m=5,第二行从a[2]开始

  • 0 1 2 3 4
  • 2 3 4 0 1
  • 3 4 0 1 2
  • 4 0 1 2 3
  • 0 1 2 3 4
  • 0 1 2 3 4

    得到的S 为1 2 3 4 0 ,得到的答案就是5

    diamond:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define endl '\n'
    void solve(){
    int n,m;
    cin>>n>>m;
    if(m==1){
        cout<<0<<'\n';
        for (int i = 0; i < n; ++i) {
            cout<<0<<'\n';
        }
        return;
    }
    if(n>=m){
        cout<<m<<endl;
    }
    else {
        cout<<n+1<<endl;
    }
    vector<int>res;
    for (int i = 0; i <m ; ++i) {
        res.push_back(i);
    }
    int g=res.size();
    for (int i = 0; i <m ; ++i) {
        res.push_back(i);
        cout<<res[i]<<' ';
    }
    cout<<endl;
    int qd=2;
    if(n<m)qd=1;
    n--;
    while (n--){
        if(qd>=m){
            for (int i = 0; i <m ; ++i) {
                cout<<i<<' ';
            }
            cout<<endl;
        }
        else {
            for (int i = qd; i <qd+m ; ++i) {
                cout<<res[i]<<' ';
            }
            cout<<endl;
            qd++;
        }
    }
    }
    signed main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while (t--){
        solve();
    }
    }

    D1. Candy Party (Easy Version)

    题意:给一个n个数的数组a,要求令每一个数减去$2^x$,然后加上一个$2^x$,最后是否可以让所有数字都相同

    思路1:易知$sum%n!=0$就是NO,我们对每一个数字进行枚举他需要什么和减去什么,32 * 32的复杂度,我们最后判断加的数组和减的数组是否相等就可以了,如果没有任何组合可以得到平均值,那么是NO

    diamond1:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define endl '\n'
    int cifang[33];
    set<int>st;
    void solve() {
    int n;
    cin >> n;
    
    vector<int> zeng(32);
    vector<int> jian(32);
    vector<int> a(n);
    int sum = 0;
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
        sum += a[i];
    }
    if (sum % n) {
        cout << "No\n";
        return;
    }
    vector<int> d1(100), d2(100);
    int vis = 1;
    for (int i = 0; i < n; ++i) {
        vis = 1;
        for (int j = 0; j < 32; ++j) {
            for (int k = 0; k < 32; ++k) {
                if (a[i] - (1ll << j) + (1ll << k) == sum / n) {
    //                    cout<<sum/n<<endl;
    //                        cout<<a[i]<<' '<<(1ll << j)<<' '<<(1ll << k)<<endl;
                    d1[j]++;
                    d2[k]++;
                    vis = 0;
                    break;
                }
            }
        }
        if (vis == 1) {
            cout << "NO\n";
            return;
        }
    }
    if (d1 == d2) {
        cout << "YES\n";
    } else {
        cout << "NO\n";
    }
    }
    signed main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while (t--){
        solve();
    }
    }

    思路2:我们可以对ai与平均值的差值进行分析,假设我们的差值的绝对值是01111,那么这两次操作就可以是10000-00001,只有这种1是连续的情况和没有1的情况才可以通过两次操作得到答案,高位1的前一位,和最低位的1,这是唯一做法,那么我们可以维护每一个值的差,当是0的时候也没关系,因为他可以当一个中转站,可以忽略,然后如果大于0,那么我们给一个高位1的前一位的1,然后拿走一个最低位的1,如果小于0,则反过来即可。最后判断每一个1是否都是0

    diamond2:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    void solve() {
    int n;
    cin >> n;
    map<int, int> mp;
    vector<int >a(n);
    int ss=0;
    for (int i = 0; i <n ; ++i) {
        cin>>a[i];
        ss+=a[i];
    }
    if(ss%n) {
        cout<<"NO\n";
        return;
    }
    int v=ss/n;
    for (int i = 0; i <n ; ++i) {
        int cha=abs(a[i]-v);
        if(cha==0)continue;
        string s=bitset<32>(cha).to_string();
        int l=-1, r = -1;
        std::reverse(s.begin(), s.end());
        for (int j = 0; j <32 ; ++j) {
            if(s[j]=='1'){
                l=j;
                break;
            }
        }
        for (int j = 31; j>=0 ; --j) {
            if(s[j]=='1'){
                r=j;
                break;
            }
        }
        for (int j = l; j <=r ; ++j) {
            if(s[j]=='0'){
                cout<<"NO\n";
                return;
            }
        }
        if(a[i]>v){
            mp[r+1]++;
            mp[l]--;
        }
        else{
            mp[r+1]--;
            mp[l]++;
        }
    }
    for (auto i:mp) {
        if(i.second!=0){
            cout<<"NO\n";
            return;
            break;
        }
    }
    cout<<"YES\n";
    }
    signed main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t=1;
    cin>>t;
    while (t--){
        solve();
    }
    }

    D2. Candy Party (Hard Version)

    题意:相比与简单版本的,他的变化是一个人可以只给一次,也可以只要一次,也可以给要都1次

    思路:我们D2和D1的做法2是同源的,我们发现这个限制,只在差值中只有一个1的时候,才出现了变化,其他情况不变,假设差值是010,原来我们是要1个100,然后给一个010,现在,我们可以只要一个010,我们可以打上标记,标记为我们可以拿两个010去换一个100,意思就是原版本我们的mp[4]--,mp[2]++,我们现在可以描述位mp[2]--,相比就是减去了两个mp[2];当我们访问到2给出了很多次,那么给出两次2,相当于要一个4,就是我们可以把2的值消掉,4的值加回来,对于每一个$2^x$,他只能和$2^x+1$次方进行交换,假设我们遍历到第2位的个数并不是0,那么我们就考虑能否把这个2的个数换位4的个数,假设我们还要得到2个2,那么我们就需要拿走一个4,必须从单个1那边来换,假设还要得到4个2,我们只需两个单1的2,就变为了0,然后得到2个4,4的个数就要+=2,然后继续判断4,如果不够则NO,反之同理

    diamond:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    void solve() {
    int n;
    cin >> n;
    map<int, int> mp;
    vector<int >a(n);
    map<int,int>dedao,shanqu;
    int ss=0;
    for (int i = 0; i <n ; ++i) {
        cin>>a[i];
        ss+=a[i];
    }
    if(ss%n) {
        cout<<"NO\n";
        return;
    }
    int v=ss/n;
    for (int i = 0; i <n ; ++i) {
        int cha=abs(a[i]-v);
        if(cha==0)continue;
        string s=bitset<32>(cha).to_string();
        int l=-1, r = -1;
        std::reverse(s.begin(), s.end());
        for (int j = 0; j <32 ; ++j) {
            if(s[j]=='1'){
                l=j;
                break;
            }
        }
        for (int j = 31; j>=0 ; --j) {
            if(s[j]=='1'){
                r=j;
                break;
            }
        }
        for (int j = l; j <=r ; ++j) {
            if(s[j]=='0'){
                cout<<"NO\n";
                return;
            }
        }
        if(a[i]>v){
            mp[r+1]++;
            mp[l]--;
            if(r==l){
                dedao[l]++;
            }
        }
        else{
            mp[r+1]--;
            mp[l]++;
            if(r==l){
                shanqu[l]++;
            }
        }
    }
    for (auto [x,y]:mp) {
        if(y!=0){
            if(y<0){
                y=abs(y);
                if(y%2==0){
                    int c=y/2;
                    if(c>abs(dedao[x])){
                        cout<<"NO\n";
                        return;
                    }
                    else{
                        mp[x+1]-=c;
                    }
                }
                else{
                    cout<<"NO\n";
                    return;
                }
            }
            else{
                y=abs(y);
                if(y%2==0){
                    int c=y/2;
                    if(c>abs(shanqu[x])){
                        cout<<"NO\n";
                        return;
                    }
                    else{
                        mp[x+1]+=c;
                    }
                }
                else{
                    cout<<"NO\n";
                    return;
                }
            }
        }
    
    }
    cout<<"YES\n";
    }
    signed main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t=1;
    cin>>t;
    while (t--){
        solve();
    }
    }
posted on 2023-09-21 10:18  IR101  阅读(24)  评论(0编辑  收藏  举报  来源