牛客练习赛79

A-炼金术师

原题链接

题意:

给一个序列,序列中的值代表一种颜色,从左到右每个元素都可以画[0,a[i]]区间的颜色,后面的会覆盖掉前面的颜色,而你可以每次选择[1,n]任意一个颜色和任意一个端点[0,r]进行画画。求最少次数画出来根序列一样的画布。

思路:因为每次后面的都会覆盖前面颜色,所以我们从后往前来考虑。实际上就是从后往前求一个递增序列。因为比后面数大的才不会被覆盖掉。

#include <bits/stdc++.h>
#define pb push_back//vector,deque
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1e6+5;
int a[N];
void solve()
{
    int t;
    cin>>t;
    while(t--){

    }
}
int main() {
    // solve();
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    int res=0,sum=-1;
    for(int i=n;i>=1;i--){
        if(a[i]>sum){
            res++;
            sum=a[i];
            // cout<<sum<<'\n';    
        }
    }
    printf("%d\n",res);
    return 0;
}

同样也可以用栈来写。

#include <bits/stdc++.h>
#define pb push_back//vector,deque
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1e5+5;
void solve()
{
    int t;
    cin>>t;
    while(t--){

    }
}
int main() {
    // solve();
    int n,x;
    cin>>n;
    stack<int>s;
    for(int i=1;i<=n;i++){
        cin>>x;
        while(s.size()&&s.top()<=x)s.pop();
        s.push(x);
    }
    cout<<s.size()<<'\n';
    return 0;
}
// 用栈比较容易出错的是没有+=,因为出现像 5 3 4 4 1这种情况是需要把第一个4弹出去的,不然只能过70%

B-刀工对决

原题链接

bfsTLE了

#include <bits/stdc++.h>
#define pb push_back//vector,deque
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1e5+5;
struct node{
    int a,b,step;
};
int bfs(int a,int b)
{
    queue<node>q;
    while(q.size())q.pop();
    q.push({a,b,0});
    while(q.size()){
        node h=q.front();
        q.pop(); 
        if(h.a==h.b){
            return h.step;
        }
        if(h.a>h.b){
            
            if(h.a%5==0)q.push({h.a*3/5,h.b,h.step+1});
            if(h.a%3==0)q.push({h.a/3,h.b,h.step+1});
        }else{
        	if(h.b%5==0)q.push({h.a,h.b*3/5,h.step+1});
            if(h.b%3==0)q.push({h.a,h.b/3,h.step+1});
            
        }
    }
    return -1;

}
void solve()
{
    int t,res=0;
    bool flag=true;
    int a,b;
    cin>>t;
    while(t--){
        cin>>a>>b;
       	int temp=bfs(a,b);
       	res+=temp;
       	if(temp==-1){
		   	flag=false;break;
		   }
//       cout<<res<<'\n';
    }
    if(flag)cout<<res;
    else cout<<-1;
    cout<<'\n';
}
int main() {
    solve();
    return 0;
}

考虑先除5,然后不断除3

#include <bits/stdc++.h>
#define pb push_back//vector,deque
#define INF 0x3f3f3f3f
#define scd(n) scanf("%d",&n)    
#define prd(n) printf("%d",n) 
using namespace std;
typedef long long ll;
const int N=1e5+5;
void solve()
{
    int t;
    scd(t);
    bool flag=true;
    int res=0;
    while(t--){
        int a,b;
        scd(a);scd(b);
        if(!flag)continue;
        int cnt1=0,cnt2=0;
        while(a%5==0){
            a/=5;
            a*=3;
            cnt1++;
        }
        while(b%5==0){
            b/=5;
            b*=3;
            cnt2++;
        }
        res+=abs(cnt1-cnt2);
        if(a>b){
            while(a!=b&&a!=1){
                a/=3;
                res++;
            }
        }else{
            while(a!=b&&b!=1){
                b/=3;
                res++;
            }
        }
        if(a!=b){
            flag=false;continue;
        }
    }
    if(flag)prd(res);
    else puts("-1");
    puts("\n");
}
int main() {
    solve();
    return 0;
}

C-小G的GCD

原题链接

题意:

gcd(x,y)被定义成求辗转相除的次数。而我们要做的是求max{gcd(i,j)}。给定n求最大的maxGCD。n<=1e18。

思路:打表找规律,最后发现竟然跟斐波那契数列有关hhh

#include <bits/stdc++.h>
#define pb push_back//vector,deque
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1e5+5;
ll f[100],res[100];
ll maxx=1e18;
void init()
{
    f[1]=1;f[2]=1;
    res[1]=1;res[2]=2;
    for(int i=3;i<=86;i++){
        f[i]=f[i-1]+f[i-2];
        res[i]=f[i]+res[i-1];
    }
    // for(int i=1;i<=86;i++)cout<<res[i]<<'\n';
}
int main() {
    // solve();
    ll n,ans;
    cin>>n;
    init();
    for(int i=1,j=2;i<=86;i++,j++){
        if(res[i]>=n){
            ans=j;break;
        }
    }
    cout<<ans<<'\n';
    
    return 0;
}
//1000000000000000000
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值