week 15

文章包含两个编程问题的解决方案。第一个问题是关于如何通过最少的字符删除操作使字符串变成回文串,提供了判断和找到最小操作数的方法。第二个问题涉及数组操作和分数最大化,通过动态规划和平方差计算最大分数。第三个问题是一个数学挑战,探讨了通过乘以2或3能否使一组数变为相同的问题,提出了二分搜索和因数分解的策略。
摘要由CSDN通过智能技术生成

给定一个字符串,你可以删除多个(可以是 0) 相同 的字符,这样操作之后,你能否得到一个回文串?如果能,求最小化删除的个数。

输入格式

多组数据。

每一组数据包含两行,分别为字符串的长度 N,以及一个仅由小写字母组成的字符串 S。

输出格式

对于每一组数据,输出一行。

如果不可能得到一个回文串,输出 −1。反之则输出最小操作次数

#include<bits/stdc++.h>
using namespace std;
char str[100005];
int len;
int judge(char a,int l,int r){
    int num=0,flag=0;
    while(l<r){
        if(str[l]!=str[r]){
            if(str[l]==a){
                num++,l++,flag=1;
            }
            else if(str[r]==a){
                num++,r--,flag=1;
            }
        }        
        if(str[l]==str[r]){
            l++,r--,flag=1;            
        }
        if(!flag){
            return -1;
        }
        flag=0;
    }
    return num;
}
void findans(){
    int l=1,r=len,ans_l,ans_r,flag2=0;
    char flag='0';
    while(l<r){
        if(str[l]!=str[r]){
            flag2=1;
            ans_l=judge(str[l],l,r);
            ans_r=judge(str[r],l,r);
            if(ans_l==ans_r==-1){
                cout<<"-1"<<endl;
            }
            else if(ans_l!=-1&&ans_r==-1){
                cout<<ans_l<<endl;
            }
            else if(ans_l==-1&&ans_r!=-1){
                cout<<ans_r<<endl;
            }
            else if(ans_l<ans_r){
                cout<<ans_l<<endl;
            }
            else{
                cout<<ans_r<<endl;
            }
            break;
        }
        l++,r--;
    }
    if(!flag2){
        cout<<"0"<<endl;
    }
}    
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>len;
        for(int i=1;i<=len;i++){
            cin>>str[i];
        }
        findans();
    }
    return 0;
}

给定一个长度为 n 的数组 a_1,a_2,…,a_n,接下来进行 n−1次操作。每次选择一个下标 x ,将 a_x 和 a_x+1合并成 a_x * a_(x+1) mod1000003,并且你会获得 (a_x−a__(x+1))^2 的分数。

所以每次操作后,数组的长度将会减 1,当最后只剩下一个元素时停止操作。输出最终能获得的最大分数。

输入格式

第一行一个数字 n。

接下来一行 n 个整数 a_1,a_2,…,a_n

输出格式

一个数,表示答案。
 

#include<bits/stdc++.h>
using namespace std;
#define mod 1000003
unsigned long long dp[305][305],num[305],x[305][305],book[305][305]; 
int n;
inline unsigned long long finddp(int l,int r){   //dp过程
    if(book[l][r]){
        return book[l][r];   //记忆化
    }
    if(l==r){
        return 0;  
    }
    else{
        for(int k=l;k<=r-1;k++){
            dp[l][r]=max(dp[l][r],finddp(l,k)+finddp(k+1,r)+(x[l][k]-x[k+1][r])*(x[l][k]-x[k+1][r]));         
        }
    }
    book[l][r]=dp[l][r];  
    return dp[l][r];
}
int main(){

    cin>>n;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            x[i][j]=1;
        }
    }
    for(int i=1;i<=n;i++){
        cin>>num[i];
    }
    for(int i=1;i<=n;i++){
        for(int k=i;k<=n;k++){
            for(int j=i;j<=k;j++){
                x[i][k]=(x[i][k]*num[j])%mod;  
            }
        }
    }

    cout<<finddp(1,n)<<endl;  
    return 0;
}

接着《饿饿 饭饭》 的故事,在两天后,食堂的工作人员回来了,整个食堂又回到了原来井井有条的状态。

两个月后,由于天气越来越热,大家的胃口越来越小了,作为食堂管理员的CC非常担心孩子们的身体健康,所以他决定开展一个活动来调动孩子们吃饭的积极性,顺便考验一下孩子们的数学水平。活动内容如下:

先让每一个孩子都抽一个球,每一个球上有一个数字, 然后给这个孩子n个数字,每一个孩子都有无数次操作机会,每一次都会选中一个数将它乘上2,或者乘上3,请问这个孩子可以通过上面的操作将这n个数都变成相同的吗?

如果回答正确,这个回答正确的孩子就可以得到一份免费的午餐,但是这对于孩子们来说是在是太困难了,但是他们都想吃到免费的午餐,所以他们都想请你告诉他们正确的答案,让他们都迟到免费的午餐。

输入格式

第1行给定一个数T,表示有T个小孩子请你告诉他正确的答案。

第2到T+1行,第1个数是每个孩子抽到的数字n,第2到n+1个数是对应的n个数字。

输出格式

如果可以变成相同的,输出YES。如果不能变成相同的,输出NO。

数据规模

1≤T≤100,1≤n≤2×105,1≤a_i≤109

数据保证∑T_i=1n≤2×105

#include<bits/stdc++.h>
using namespace std;
inline long long search(long long x,long long a){  //二分搜索
    int l=0,r=50;
    while(l!=r-1){
        int mid=(l+r)/2;
        if(x%(int)pow(a,mid)){
            r=mid;
        }
        else{
            l=mid;
        }
    }
    return (long long)pow(a,l);
}
inline long long findlea(long long num){  
    while(1){
        if(!(num%2)){
            num/=search(num,2);     //除以2
            continue;
        }
        else if(!(num%3)){
            num/=search(num,3);  //除以3
            continue;
        }
        break;
    }
    return num;
}
int main(){
    long long t,n,num,flag,flag0=0;
    scanf("%lld",&t);
    for(int i=1;i<=t;i++){
        scanf("%lld",&n);
        scanf("%lld",&num);
        flag=findlea(num);
        for(int a=2;a<=n;a++){
            scanf("%lld",&num);
            if(findlea(num)!=flag){   //如果x不同就代表不行
                flag0=1;
            }
        }
        if(!flag0){
            printf("YES\n");      
        }
        else{
            printf("NO\n");
        }
        flag0=0;
    }
    return 0;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值