[蓝桥杯]2018A-倍数问题

/*刚开始的思路是直接搜索暴力,很显然wa了,时间超限只过了20%(可能剩下的80%要求优化啥的,编者没有想到,但感觉应该不没啥优化的点了,可能这个题目本来的方法就不是搜索吧)*/

后面看了别人的题解才有所感悟,其实处理方法不久前才接触过
1.三个数的和对k取余结果是0,可见这三个数对k取余的和对k取余是0。( (a+b+c)%k==(a%k+b%k+c%k)%k )
2.可以排序后利用二维栈将余数相同的数按照从小到打的顺序存储(那么在出栈的时候就是从大到小了)
3.因为题目只需要求三个数,二重循环+判断就可以选出最大的和了
这个是之前没有AC的深搜写法,时间超限,只过了20%(如果有大佬可以有优化方案,评论区告诉一下,谢谢了)
#include<bits/stdc++.h>
using namespace std;
int num[100005];
int vis[100005];
int n,k,ans;
inline void dfs(int st,int sum,int cn){
     if(cn>3){
        if(sum%k==0){
            ans=max(ans,sum);
            return ;
        } else {
            return ;
        }
     }
     for(int i=st;i<=n;i++){
        if(!vis[i]){
            vis[i]=1;
            dfs(i,sum+num[i],cn+1);
            vis[i]=0;//利用回溯
        }
     }
}
int main(){
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        scanf("%d",&num[i]);
    }
    sort(num+1,num+1+n,greater<int>());
    dfs(1,0,1);
    cout<<ans<<endl;
    return 0;
}

这个是利用二维栈来解决(博主认为只是寻找3个数,可以使用,要是要选的数多了,这个方法是不是可以要打一个问号了,但是这个方法确实是一个不错的方法)

#include<bits/stdc++.h>
using namespace std;
int a[100005];
stack<int>num[1005];
int n,k;
int main(){
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++){
        num[a[i]%k].push(a[i]);//利用二维栈来存储余数相同的数,并且是从小到大(出栈的时候就是从大到小)
    }
    int res=0;
    for(int i=0;i<k;i++){
        if(num[i].empty()){
            continue;//如果第一个余数已经没有了,那么将跳过这个余数
        }
        for(int j=0;j<k;j++){
            if(num[j].empty()){
                continue;//如果第二个余数没有了,那么将直接跳过这个余数
            }
            int rm=(k-i-j+k)%k;//找到第三个数应该的余数
            int tmp=0,ans1,ans2,ans3;
            if(rm<j){
                continue;
            }
            if(num[i].size()){
                ans1=num[i].top();
                tmp+=ans1;
                num[i].pop();
                if(num[j].size()){
                    ans2=num[j].top();
                    tmp+=ans2;
                    num[j].pop();
                    if(num[rm].size()){
                        ans3=num[rm].top();
                        tmp+=ans3;
                        num[rm].pop();
                        res=max(res,tmp);
                        num[rm].push(ans3);
                    }
                    num[j].push(ans2);
                }
            }
            num[i].push(ans1);
        }
    }
    cout<<res<<endl;
    return 0;
}
/*总结:利用下表存余数或者其他数,这种方法是本题目的一个核心之一了*/

由于发布的时间太晚了,还有一个类似的题目来不及写,希望大家可以后续关注,一键三连哦.(补博客链接:https://blog.csdn.net/qq_46037076/article/details/115322537)

20岁的年纪不应该选择脱单,应该选择脱贫。

 

猜你喜欢

转载自blog.csdn.net/qq_46037076/article/details/115314686
今日推荐