牛客寒假算法集训5-总结

A

时间复杂度:
O(n)

AC代码:

#include <iostream>

using namespace std;

int n,cnt;
int a[110];

bool is_isprime(int x)
{
    if(x<2) return false;
    
    for(int i=2;i<=x/i;i++)
        if(x%i==0) return false;
    
    return true;
}

int main()
{
    cin>>n;
    for(int i=0;i<n;i++) 
    {
        cin>>a[i];
        if(a[i]==1) continue;
        if(is_isprime(a[i])) cnt++;
        else cnt++;
    }
    
    cout<<cnt;
    
    return 0;
}

B

思路:
在两个数字之间插入x个0,可以等效为这两个数字同时减去x

时间复杂度:
O(n)

AC代码:

#include <bits/stdc++.h>

using namespace std;

const int N=1e5+10;

typedef long long ll;

ll n,cnt;
ll a[N];
ll x;
ll sum;
ll q,y;

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    
    for(int i=0,j=0;i<=n;i++,j++)
    {
        if(i==0) 
        {
            x=a[1];
            cnt+=x-1;
            q=cnt;
            continue;
        }
        if(i==n) y=a[n];
        else y=min(a[i],a[i+1]);
        int p=y-1;
        sum+=a[i];
        if(y==1) continue;
        ll res=p+q+j;
        if(sum/res>=1) 
        {
            cnt+=p;sum=0;q=p;j=0;
        }
        else 
        {    if(sum-q-j<=p)
            {
                cnt+=sum-q-j;
                q=sum-q-j;
                sum=0;
                j=0;
            }
        }
    }
    cout<<cnt;
    return 0;
}

I

思路:
简单模拟,签到题

时间复杂度:
O(1)

AC代码:

#include <iostream>
#include <cmath>

using namespace std;

typedef long long ll;

ll t,a,k,d;
ll s;
ll l,r;
bool p;

int main()
{
    cin>>t>>a>>k;
    if(t<0)
    {
        s=0;
        int l=-k,r=k;
        while(s>=t)
        {
            if(a>=l&&a<=r) 
            {   
                d+=abs(a-s);
                d+=abs(t-a);
                p=true;
                break;
            }
            s--;l--;r--;d++;
        }
        if(!p)
        {
            s++;d--;
            d+=abs(s-a)*2;
        }
    }
    else if(t==0) d=abs(s-a);
    else
    {	s=0;
     int l=-k,r=k;
     while(s<=t)
     {
         if(a>=l&&a<=r) 
         {   
             d+=abs(a-s);
             d+=abs(t-a);
             p=true;
             break;
         }
         s++;l++;r++;d++;
     }
     if(!p)
        {
            s--;d--;
            d+=abs(s-a)*2;
        }
    }
    cout<<d;
    return 0;     
}

L

思路:
枚举

时间复杂度:
o(1)

AC代码:

#include <iostream>

using namespace std;

const int N=1010;
int n,x,cnt,res;

int main()
{
    cin>>n>>x;
    cnt=(n+x)/2;
    res=n-cnt;
    if(cnt-res!=x) cout<<-1; 
    else cout<<cnt<<' '<<res;
    return 0;
}

M

思路:
一个很重要的思路:当可以通过删除操作得到两个以上连通块时,最多只需要两次删除操作;

比如:

a:1 2 3 4 5 6

b:4 5 6 1 3 2

随意找两个处于相同位置的数字,比如数组a中,3在第三列,数组b中,6也在第三列,那么只需要删去3和6就能得到两个以上连通块;

另外,若使用a[x]表示数字x在数组a上的位置,用b[x]表示数字x在数组b上的位置,那么我们知道:当时,似乎只需要一次操作就能将原来的排列分成两个连通块;

但是需要注意一点:当时,可能会是这种情况:

1 2 3 4

1 3 2 4

故此时需要进行特判(判断是否在头部或者尾部);

至于什么情况下输出-1,简单思考后,我们可以知道只有两种情况
(1)n==1时
(2)n==2且数组a和b相同时

时间复杂度:
O(∑n)

AC代码:

#include <bits/stdc++.h>

using namespace std;

const int N=1e5+10;
int T;
bool k;
int n;
int a[N],b[N];

int main()
{
    cin>>T;
    while(T--)
    {
        cin>>n;k=false;
        for(int i=1;i<=n;i++) cin>>a[i];
        for(int i=1;i<=n;i++) cin>>b[i];
        if(n==1) cout<<-1<<endl;
        else if(n==2)
        {
            for(int i=1;i<=2;i++)
            {
                if(a[i]==b[i]) {cout<<-1<<endl;k=true;break;}
            }
            if(!k) cout<<1<<endl;
        }
        else 
        {
            for(int i=2;i<=n-1;i++)
            {
                if(a[i]==b[i]) {cout<<1<<endl;k=true;break;}
                if(a[i]==b[i-1]) {cout<<1<<endl;k=true;break;}
                if(a[i]==b[i+1]) {cout<<1<<endl;k=true;break;}
            }
            if(!k)
            {
                if(a[1]==b[2]||a[n]==b[n-1]) cout<<1<<endl;
                else  cout<<2<<endl;
            }
        }
        
    }
    return 0;
}
posted @   Eric`  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示