ACM训练日记—3月19日

       还是补昨天的博客,昨天卡在一道题上快卡疯了,算法很简单,但是细节巨多,超级多,真是考验我基本功。我这次还是先整理下最近做的比赛题目并整理下hiho上的重点题目。

     牛客练习赛13

1,幸运数字1

     水题,找4和7谁出现的次数多。

2,幸运数字2

定义一个数字为幸运数字当且仅当它的所有数位都是4或者7。
比如说,47、744、4都是幸运数字而5、17、467都不是。
定义next(x)为大于等于x的第一个幸运数字。给定l,r,请求出next(l) + next(l + 1) + ... + next(r - 1) + next(r)。

      因为数据量只有1e9,所以只包含4和7的数字只有500多个,所以先用深搜打表,排序,然后暴力一遍l到r

vector<ll>q;
void dfs(ll x,int cnt)
{
    if(cnt==10) return ;
    ll ans;

    ans=x*10+4;
    q.push_back(ans);
    dfs(ans,cnt+1);

    ans=x*10+7;
    q.push_back(ans);
    dfs(ans,cnt+1);
}
int main()
{
    q.clear();
    q.push_back(4);
    q.push_back(7);
    dfs(4,1);
    dfs(7,1);
    sort(q.begin(),q.end());
    ll l,r;
    scanf("%lld%lld",&l,&r);
    ll ans=0;
    for(int i=0;i<q.size();i++)
    {
        if(q[i]>=l&&q[i]<=r)
        {
            ans=ans+q[i]*(q[i]-l+1);
            l=q[i]+1;
            continue;
        }
        if(q[i]>r)
        {
            ans=ans+q[i]*(r-l+1);//这里是个细节,因为l<=r,所以还有一个大于r的数要处理
            break;
        }
    }
    cout<<ans<<endl;
}

3,幸运数字3

定义一个数字为幸运数字当且仅当它的所有数位都是4或者7。比如说,47、744、4都是幸运数字而5、17、467都不是。假设现在有一个数字d,现在想在d上重复k次操作。假设d有n位,用d1,d2,...,dn表示。对于每次操作,我们想要找到最小的x (x < n),使得dx=4并且dx+1=7。如果x为奇数,那么我们把dx和dx+1都变成4;否则,如果x为偶数,我们把dx和dx+1都变成7;如果不存在x,那么我们不做任何修改。现在请问k次操作以后,d会变成什么样子。

      这个有规律的,先找到47出现,判断4是偶数上还是奇数,只有当偶数时才会对前面的数产生影响,此时前面如果是4,一定是奇数位上,此时只对后面有影响,继续向后就可以了。

char str[100005];
int main()
{
    ll n,k;
    scanf("%lld%lld",&n,&k);
    scanf("%s",str);
    for(int i=0;i<n;i++)
    {
        if(k==0) break;
        if(str[i]=='4'&&str[i+1]=='7')
        {
            if((i+1)%2==1)
            {
                if(k>=1)
                {
                    str[i]='4';
                    str[i+1]='4';
                    k--;
                }
                else break;
            }
            else
            {
                if(k>=1)
                {
                    str[i]='7';
                    k--;
                }
                else break;
                if(i==0) continue;
                if(str[i-1]=='4')
                {
                    if(k%2==1) str[i]='4';
                    else str[i]='7';
                    break;
                }
                else {continue;}
            }
        }
    }
    cout<<str<<endl;
}

       牛客小白月赛1

I题:あなたの蛙が帰っています

毕竟G题还没完全弄懂。其他都很水。

        I题之前一直没把题目读懂,读懂后简直后悔死了,就是裸的卡特兰数。之前没特别关注过卡特兰数对单调栈的应用,果然吃亏了。

http://blog.sina.com.cn/s/blog_6aefe4250101asv5.html

       hihocoder 1604 股票价格2

题目:小Hi最近在关注股票,为了计算股票可能的盈利,他获取了一只股票最近N天的价格A1~AN。
在小Hi的策略中,每天可以在下列三种操作中选取一种:
1.什么也不做;
2.按照当天的价格买进一个单位的股票;
3.按照当天的价格卖出部分或所有股票。
现在小Hi希望能够知道,如果在N天前手中持有的股票数为0,并且假设拥有无限的金钱,在这N天结束能够获得的最大利润是多少?

       这个题刚开始我是想用线段树做的,用线段树处理出来区间最大值,然后从左到右依次处理一直到最后,最差的情况也就是单调递减的序列,也就是nlog(n)。可后来转换思路,发现如果从后向前处理,不断更新最大值进行加和,代码更简单,只要n就可以。这道题其实这个转换思路比较印象深刻。

int a[1000005];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    int ans=0;
    int maxn=a[n];
    for(int i=(n-1);i>=1;i--)
    {
        if(a[i]<=maxn) ans+=(maxn-a[i]);
        else
        {
            maxn=a[i];
        }
    }
    cout<<ans<<endl;
}

      有点晚了,先整理这些,晚安

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值