2021-11-12

本文讨论了两道编程题目,涉及字符串的字典序最小子序列查找和数组的出现次数变换。第一部分介绍了如何找到字符串中字典序最小的子序列,第二部分讲解了如何预处理数组以应对询问出现次数的问题。通过这两个问题展示了对字符串和数组操作的理解及算法优化技巧。
摘要由CSDN通过智能技术生成

A. Two Subsequences

题意:

给你一个字符串 s。您需要找到两个非空字符串 a 和 b,以满足以下条件:
字符串 a 和 b 都是 s 的子序列。
对于每个索引 i,字符串 s 的字符 si 必须恰好属于字符串 a 或 b 之一。
字符串 a 是字典序最小可能的;字符串 b 可以是任何可能的字符串。
给定字符串 s,打印任何有效的 a 和 b。

题解:

字典序最小当然就是s中的最小字母了,b可以是任意,那么就是s减去a后的字符串了

#include<bits/stdc++.h>
using namespace std;
int main()
{
        int t;
        cin >> t;
        while (t--)
        {
                string s;
                cin >> s;
                int pos = 0;
                for (int i = 0; i < s.size(); ++i)
                {
                        if (s[i] < s[pos])
                        {
                                pos = i;
                        }
                }
                string ans = "";
                for (int i = 0; i < s.size(); ++i) if (i != pos)
                        {
                                ans += s[i];
                        }

                cout << s[pos] << " " << ans << endl;
        }
        return 0;
}

B. Divine Array

题意:

有一个数组a,现在对其进行变换,将第i个位置上的数字a[i]变成a[i]的出现次数。

给出q个询问,每个询问给出x,k,代表第k次变换后,a[x]的值为多少?

题解:

在经过一定的变换次数后,整个数组会保持不变,所以可以在询问前预处理出所有的情况。

#include<bits/stdc++.h>
using namespace std;
int main()
{
        int t;
        cin >> t;
        while (t--)
        {
                string s;
                cin >> s;
                int pos = 0;
                for (int i = 0; i < s.size(); ++i)
                {
                        if (s[i] < s[pos])
                        {
                                pos = i;
                        }
                }
                string ans = "";
                for (int i = 0; i < s.size(); ++i) if (i != pos)
                        {
                                ans += s[i];
                        }

                cout << s[pos] << " " << ans << endl;
        }
        return 0;
}

C. Array Elimination

题意:

每次选k个数,令x=a[1]&a[2]&a[3]......a[k], 并且a[1] - x, a[2] - x .... a[k] - x, 问是否能将数组a的所有元素变为0,从小到大输出所有k的可能值。

题解:

把所有数都变为0,也就是将所有数的数位变为0。每次操作,减去的是k个数的与值。所以,为了将一个数位变为0,减去的这个与值的该数位也要为0。为了让与值的该数位为0,那么挑选的k个位置上的数该数位都为1。

因为可以操作若干次,所以对于一列数位的x个1来说,可以选择x的因子y个1,能够将这y个数的该数位都化为0,然后进行若干次。

综合考虑所有数位,那么满足条件的 k 就为30个数位中,1的个数的所有公约数。
 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxx=2e5+10;
int a[maxx];
int b[maxx];
int gcd(int a,int b)
{
    if(!b)
        return a;
    return gcd(b,a%b);
}
int main()
{
    int t,n;
    cin>>t;
    while(t--)
    {
       memset(b,0,sizeof(b));
       cin>>n;
       for(int i=1;i<=n;i++)
       {
           cin>>a[i];
           for(int j=0;j<=30;j++)
           {
               if((a[i]>>j)&1)
                {
                    int p=a[i]>>j;
                    int pp=(a[i]>>j)&1;
                    //cout<<a[i]<<" "<<j<<" "<<p<<" "<<pp<<endl;
                    b[j]++;
                }
           }
       }
       int x=0;
       for(int i=0;i<=30;i++)
       {
           if(b[i])
            x=gcd(x,b[i]);
       }
       for(int i=1;i<=n;i++)
       {
           if(x%i==0)
           {
               cout<<i<<" ";
           }
       }
       cout<<endl;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值