牛客练习赛13

A.幸运数字Ⅰ

这题很简单啊,能明显答案只有三种情况,-1或4或7。

想44,77,47......这些都没有4和7优(数量上和字典序上)

我们只要找出4和7的个数,判断一下是否为-1。如果4的个数>=7的个数就输出4,否则7

时间复杂度:O(n)

#include<bits/stdc++.h>
using namespace std;
int a,b;
char s[5005];
int main()
{
    scanf("%s",s+1);
    int n=strlen(s+1);
    for(int i=1;i<=n;i++)
        if(s[i]=='4')a++;
        else if(s[i]=='7')b++;
    if(a==0&&b==0)cout<<-1;
    else if(a>=b)cout<<4;
    else cout<<7;
    return 0;
}

B. 幸运数字Ⅱ

首先,我们发现l和r很大,直接O(n)枚举会T,怎么办?

我们发现l到r中有很多连续的数,他们的next()是一样的,我们可以把这些数一起计算。

还有就是要把幸运数字给晒出了,我们假设现在有一个幸运数字a,我们就能构造出a * 10+4和a * 10+7是幸运数字

时间复杂度:O(50)

#include<bits/stdc++.h>
using namespace std;
int l,r,cnt,a[10005];
void dfs(long long x)
{
    if(x>1000000000)return;
    a[++cnt]=(int)x;
    dfs(x*10+4);
    dfs(x*10+7);
}
int main()
{
    dfs((long long)4);
    dfs((long long)7);
    sort(a+1,a+cnt+1);
    scanf("%d%d",&l,&r);
    long long ans=0;
    for(int i=1;i<=cnt;i++)
        if(a[i]>=l)
        {
            if(a[i]>=r){ans+=a[i]*(r-l+1); break;}
            else ans+=a[i]*(a[i]-l+1),l=a[i]+1;
        }
    cout<<ans;
    return 0;
}

C.幸运数字Ⅲ

这题难度中等。

我一看到题目说,k<=1000000000就知道这题肯定有什么特殊的性质。

果然,当x为奇数时,a[x]=4,a[x+1]=7,a[x+2]=7的话,就会陷入循环。

同样的,当x为偶数时,a[x-1]=4,a[x]=4,a[x+1]=7的话,也会陷入循环。

陷入循环的话就好做了,直接把k%2就行了。

没进入循环的话,就线性扫过去就好了

时间复杂度:O(n)

#include<bits/stdc++.h>
using namespace std;
int n,k;
char s[1000005];
int main()
{
    scanf("%d%d",&n,&k);
    scanf("%s",s+1);
    for(int i=1;i0;i++)
        if(s[i]=='4'&&s[i+1]=='7')
        {
            if(i%2==1)
            {
                if(s[i+2]=='7')k%=2;
            }
            else
            {
                if(s[i-1]=='4')k%=2;
            }
            if(k)
            {
                k--;
                if(i%2==1)s[i+1]='4';
                else s[i]='7';
            }
        }
    printf("%s",s+1);
    return 0;
}

D.幸运数字Ⅳ

这题是好题,有思维难度。

我们需要发现 这是大于k(1000000000)的。

所以只有最后13个数会换顺序,前面的数都是不变的。

所以前面的数位置=值,即一个数值是幸运数字,它的位置也是幸运数字。

我们对于后13个数,直接13*13暴力判断每一位上的数应该是从哪一位换过来的,再统计一下就好了

时间复杂度:O(13*13)

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+5;
int n,m,cnt,q,p,ans,x,tmp,a[N],jc[N];
bool vis[N];
void dfs(int x)
{
    if(x>1000000000)return;
    a[++cnt]=x;
    dfs(x*10+4);
    dfs(x*10+7);
}
bool pd(int x)
{
       if(a[lower_bound(a+1,a+cnt+1,x)-a]==x)return true;
       return false;
}
signed main()
{
    dfs(4);
    dfs(7);
    a[++cnt]=4444444444;
    sort(a+1,a+cnt+1);
    scanf("%lld%lld",&n,&m);
    jc[0]=1;
    for(int i=1;i<=13;i++)jc[i]=jc[i-1]*i;
    q=1;
    for(int i=1;i<=13;i++)
    {
        q*=i;
        p=i;
        if(q>=m)break;
    }
    if(p>n)
    {
        puts("-1");
        return 0;
    }
    for(int i=1;i<=cnt;i++)
    {
        if(a[i]>=n-p+1)break;
        ans++;
    }
    for(int i=n-p+1;i<=n;i++)
    {
        x=m/jc[n-i]+(m%jc[n-i]!=0);
        int gs=0;
        int j;
        for(j=1;j<=p;j++)
            if(!vis[j])
                if(++gs==x)
                {
                    vis[j]=true;
                    break;
                }
        if(pd(i)&&pd(n-p+j))ans++;
        m%=jc[n-i];
        if(!m)m=jc[n-i];
    }
    cout<<ans;
    return 0;
}

E:乌龟跑步

一道简单的dp题。

表示前i个操作,改变了j次,当前在k,方向是向前(后)的。

注意,因为是可以往回走的,所以我们可以把起点设在200的位置,这样就不用开map了。

if(s[i]=='T')
{
    f[i][j][k][1]|=f[i-1][j][k][0];//转头
    f[i][j][k][0]|=f[i-1][j][k][1];//转头
    if(j>0)
    {
        f[i][j][k][1]|=f[i-1][j-1][k-1][1];//转头变成向前走
        f[i][j][k][0]|=f[i-1][j-1][k+1][0];//转头变成向前走
    }
}
else{
    f[i][j][k][1]|=f[i-1][j][k-1][1];//向前走
    f[i][j][k][0]|=f[i-1][j][k+1][0];//向前走
    if(j>0)
    {
        f[i][j][k][1]|=f[i-1][j-1][k][0];//向前走变成转头
        f[i][j][k][0]|=f[i-1][j-1][k][1];//向前走变成转头
    }
}

时间复杂度:O(n * m * 200 * 2)

#include<bits/stdc++.h>
using namespace std;
const int N=135;
int n,m,f[N][N][305][2];
char s[N];
int main()
{
    scanf("%s%d",s+1,&n);
    int m=strlen(s+1);
    f[0][0][200][1]=1;
    for(int i=1;i<=m;i++)
        for(int j=0;j<=min(i,n);j++)
            for(int k=100;k<=300;k++)
            {
                if(s[i]=='T')
                {
                    f[i][j][k][1]|=f[i-1][j][k][0];
                    f[i][j][k][0]|=f[i-1][j][k][1];
                    if(j>0)
                    {
                        f[i][j][k][1]|=f[i-1][j-1][k-1][1];
                        f[i][j][k][0]|=f[i-1][j-1][k+1][0];
                    }
                }
                else{
                    f[i][j][k][1]|=f[i-1][j][k-1][1];
                    f[i][j][k][0]|=f[i-1][j][k+1][0];
                    if(j>0)
                    {
                        f[i][j][k][1]|=f[i-1][j-1][k][0];
                        f[i][j][k][0]|=f[i-1][j-1][k][1];
                    }
                }
            }
    int ans=0;
    for(int j=100;j<=300;j++)
        if(f[m][n][j][0]||f[m][n][j][1])ans=max(ans,abs(200-j));
    cout<<ans;
    return 0;
}

F.m皇后

这题相对简单,看到这题就知道只要拍一下序,统计一下就好了。

比如要统计每个点上方和下方是否有点这个问题。

我们就只要按x轴排序,这时x轴相同的就会在一起了,我们就可以方便的判断每个点上方和下方是否有点这个问题了。

其他的同理。

时间复杂度:O(nlog(n))

#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int n,m,sum[N],ans[20];
struct node{
    int x,y,id;
}a[N];
bool cmp1(node a,node b)
{
    return a.x==b.x?a.y<b.y:a.x<b.x;
}
bool cmp2(node a,node b)
{
    return a.y==b.y?a.x<b.x:a.y<b.y;
}
bool cmp3(node a,node b)
{
    return a.y-a.x==b.y-b.x?a.x<b.x:a.y-a.x<b.y-b.x;
}
bool cmp4(node a,node b)
{
    return a.y+a.x==b.y+b.x?a.x<b.x:a.y+a.x<b.y+b.x;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&a[i].x,&a[i].y);
        a[i].id=i;
    }
    sort(a+1,a+m+1,cmp1);
    for(int i=2;i<=m;i++)
        if(a[i].x==a[i-1].x)
        {
            sum[a[i].id]++;
            sum[a[i-1].id]++;
        }
    sort(a+1,a+m+1,cmp2);
    for(int i=2;i<=m;i++)
        if(a[i].y==a[i-1].y)
        {
            sum[a[i].id]++;
            sum[a[i-1].id]++;
        }
    sort(a+1,a+m+1,cmp3);
    for(int i=2;i<=m;i++)
        if(a[i].y-a[i].x==a[i-1].y-a[i-1].x)
        {
            sum[a[i].id]++;
            sum[a[i-1].id]++;
        }
    sort(a+1,a+m+1,cmp4);
    for(int i=2;i<=m;i++)
        if(a[i].x+a[i].y==a[i-1].x+a[i-1].y)
        {
            sum[a[i].id]++;
            sum[a[i-1].id]++;
        }
    for(int i=1;i<=m;i++)ans[sum[i]]++;
    for(int i=0;i<=8;i++)printf("%d ",ans[i]);
    return 0;
}
全部评论
谢谢
点赞
送花
回复
分享
发布于 2019-04-08 12:32

相关推荐

点赞 评论 收藏
转发
4 4 评论
分享
牛客网
牛客企业服务