Codeforces Round #295 (Div. 2) A+B+C

字符串操作与算法题解
本文探讨了如何通过编程解决字符串中的复杂问题,包括检查字符串是否包含所有英文字母、实现数学运算步骤优化以及字符串匹配计数等核心算法题解。

A题:找出字符串中是否出现了26个英文字母,不区分大小写

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
char str[200] ;
int a[30] , b[30] ;
int main()
{
    int n , i ;
    scanf("%d", &n) ;
    scanf("%s", str) ;
    memset(a,0,sizeof(a)) ;
    memset(b,0,sizeof(b)) ;
    for(i = 0 ; i < n ; i++)
    {
        if( str[i] >= 'a' && str[i] <= 'z' )
            a[ str[i]-'a' ] = 1 ;
        if( str[i] >= 'A' && str[i] <= 'Z' )
            b[ str[i]-'A' ] = 1 ;
    }
    for(i = 0 ; i < 26 ; i++)
        if( a[i] == 0 && b[i] == 0 )
            break ;
    if( i < 26 )
        printf("NO\n") ;
    else
        printf("YES\n") ;
    return 0 ;
}


B题:给出两种操作方式,一种是乘2,一种是减一,给出初始数n,问可以可以达到m,可以输出步数,否则输出任意一个数。

进行广搜,看是否可以找到那个数。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std ;
struct node{
    int a , t ;
}p , q ;
queue <node> que ;
int a[30000] ;
int main()
{
    int n , m , num , flag ;
    while( scanf("%d %d", &n, &m) != EOF )
    {
        memset(a,0,sizeof(a)) ;
        flag = 0 ;
        num = 0 ;
        p.a = n ;
        p.t = 0 ;
        while( !que.empty() )
            que.pop() ;
        que.push(p) ;
        while( !que.empty() )
        {
            p = que.front() ;
            que.pop() ;
            if( p.a == m )
            {
                flag = 1 ;
                break ;
            }
            q = p ;
            q.a-- ;
            q.t++ ;
            if( q.a >= 0 && a[ q.a ] == 0 )
            {
                a[ q.a ] = 1 ;
                que.push(q) ;
            }
            q = p ;
            q.a *= 2 ;
            q.t++ ;
            if( q.a >= 0 && q.a <= 20000 && a[ q.a ] == 0 )
            {
                a[ q.a ] = 1 ;
                que.push(q) ;
            }
        }
        if( flag == 1 )
            printf("%d\n", p.t) ;
        else
            printf("0") ;
    }
    return 0 ;
}


 

C题:数学题,按照公式的话,两个串从任意一个位置开始匹配都会统计到,那么找出给定字符串的出现次数最多的字符有几个,结果也就是它的n次方。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define MOD (int)(1e9+7)
#define LL __int64
char str[200000] ;
int num[10] ;
LL pow(LL a,LL b)
{
    if( b == 1 )
        return a ;
    LL c = pow(a,b/2) ;
    c = c*c % MOD ;
    if( b % 2 )
        c = c * a % MOD ;
    return c;
}
int main()
{
    int i , n ;
    memset(num,0,sizeof(num)) ;
    scanf("%d", &n) ;
    scanf("%s", str) ;
    for(i = 0 ; i < n ; i++)
    {
        if( str[i] == 'A' )
            num[0]++ ;
        if( str[i] == 'C' )
            num[1]++ ;
        if( str[i] == 'G' )
            num[2]++ ;
        if( str[i] == 'T' )
            num[3]++ ;
    }
    int max1 = 0 , k = 0 ;
    for(i = 0 ; i < 4 ; i++)
        max1 = max( max1,num[i] ) ;
    for(i = 0 ; i < 4 ; i++)
        if( num[i] == max1 )
            k++ ;
    printf("%I64d\n", pow(k,n) ) ;
    return 0 ;
}


 

### 关于 Codeforces Round 997 Div. 2 的题目及解析 #### A. XOR Mixup 在这个问题中,给定了两个整数 \(a\) 和 \(b\) ,以及一个正整数 \(k\) 。目标是在不超过 \(k\) 步内通过交换 \(a\) 和 \(b\) 中任意一位来使得两者相等。如果可以在指定步数内完成,则返回 "YES";否则返回 "NO"[^1]。 对于这个问题的一个有效解决方案是计算不同位的数量并判断其是否小于等于两倍的 k 值加上 a 和 b 的二进制表示中最右边不同的位置索引之差。这是因为每一步最多能改变一对不匹配的位置状态。 ```cpp #include <bits/stdc++.h> using namespace std; int main() { int t; cin >> t; while(t--) { long long a, b, k; cin >> a >> b >> k; bitset<32> ba(a), bb(b); int diff = 0; for(int i=0; i<32; ++i){ if(ba[i]!=bb[i])++diff; } cout << ((abs(__builtin_ctzll(a ^ b)) + 2 * k >= diff) ? "YES\n":"NO\n"); } } ``` #### B. Array Shrinking 此题描述了一个数组缩小的过程:允许选取连续子数组并将它们替换为其最大公约数值(GCD),直到整个数组变成单个元素为止。询问最终剩余的那个唯一数字是什么样的最小可能值[^2]? 解决方法涉及到动态规划的思想——维护一个二维表 dp[][],其中dp\[l\]\[r\] 表达的是区间 \([l,r]\) 能够被压缩成的最大 GCD 数字。转移方程基于枚举中间点 m 来分割原区间为更小子区间的组合方式实现更新。 ```cpp const int N = 2e5+7; long long gcd(long long a,long long b){return !b?a:gcd(b,a%b);} vector<int> v(N); unordered_map<long long,int> mp[N]; void solve(){ int n; scanf("%d",&n); for(int i=1;i<=n;++i)v[i]=rand()%N+1; memset(mp,0,sizeof(mp)); for(int len=1;len<=n;++len) for(int l=1;l+len-1<=n;++l){ int r=l+len-1; if(len==1)mp[l][v[l]]=1; else{ unordered_set<long long> st; for(auto &p : mp[l]) if(p.second>=len-1&&gcd(v[r],p.first)==v[r]){ printf("0");exit(0); }else{st.insert(gcd(v[r],p.first));} for(auto x:st)mp[l][x]++; } } puts(to_string(mp[1].begin()->first).c_str()); } signed main(){solve();} ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值