CodeForces - 1373

CodeForces - 1373

A - Donut Shops

1个的时候,2最亏,店1最有可能比店2便宜
买b个的时候,2最赚,店2最有可能比店1便宜
比较这两种情况即可

ll a,b,c;
int ans1,ans2,t;
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld%lld",&a,&b,&c);
        if (a*b>c)ans2=b;
        else ans2=-1;
        if (a<c)ans1=1;
        else ans1=-1;
        printf("%d %d\n",ans1,ans2);
    }
    return 0;
}



B - 01 Game

直接判断01数量即可,因为只要01都存在于这个字符串中,必然会有相邻的地方
不论如何都可以一起删除

int t;
char s[maxn];
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        int num0=0,num1=0;
        scanf("%s",s);
        repp(i,0,strlen(s))s[i]=='0'?num0++:num1++;
        if (min(num0,num1)%2==0)printf("NET\n");
        else printf("DA\n");
    }
    return 0;
}



C - Pluses and Minuses

now表示能够遍历到某个位置x所需的最小cur
如果b[i]>now说明[now,b[i]-1]这个区间的数都可以遍历到位置i,res共加了i+1int t,b[maxn];
char s[maxn];
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",s);
        int sz=strlen(s),num1=0,num2=0,now=0;
        ll res=sz;
        repp(i,0,sz)s[i]=='+'?num1++:num2++,b[i]=num2-num1;
        repp(i,0,sz)
        {
            if (b[i]<=now)continue;
            res+=1ll*(b[i]-now)*(i+1);
            now=b[i];
        }
        WW(res);
    }
    return 0;
}



D - Maximum Sum on Even Positions

题意:使偶数位置的数的加和最大
首先需要明确:置换区间的长度必然是偶数,置换奇数长度的区间是无意义的
给出两个例子便于理解:
原数组:2 5 6 1 7 偶数位置加和=2+6+7
假设置换区间 [ 1 , 2 ] [1,2] [1,2]
得到数组:2 6 5 1 7 偶数位置加和=2+5+7
变化量就等于5和6的差abs(5-6)=1

reverse区间的实质就是交换区间内的相邻数,这个相邻是不含重叠的相邻
假设置换区间[1,4],则变化量是 ( a 2 − a 1 ) + ( a 4 − a 3 ) (a_2-a_1)+(a_4-a_3) (a2a1)+(a4a3)或者 ( a 1 − a 2 ) + ( a 3 − a 4 ) (a_1-a_2)+(a_3-a_4) (a1a2)+(a3a4)

于是,问题就简化为了,选取一段区间等价于求最大字段和
套用最大字段和模板即可。注意有两个方向。

int t,n,a[maxn];
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        ll ans=0,ans1=0,ans2=0;
        scanf("%d",&n);
        rep(i,1,n)
        {
            scanf("%d",&a[i]);
            if (i%2==1)ans+=a[i];
        }
        ll cnt=0;
        for (int i=1;i<=n-1;i+=2)
        {
            if (cnt>0)cnt+=a[i+1]-a[i];
            else cnt=a[i+1]-a[i];
            ans1=max(ans1,cnt);
        }
        cnt=0;
        for (int i=2;i<=n-1;i+=2)
        {
            if (cnt>0)cnt+=a[i]-a[i+1];
            else cnt=a[i]-a[i+1];
            ans2=max(ans2,cnt);
        }
        WW(ans+max(ans1,ans2));
    }
    return 0;
}



E - Sum of Digits

1.对于k=0的,做了特判处理,这种情况只要尽可能多的往后面放9就可以了
2.对于x=0时,做了特判处理,由于用到了map
3.当n比较小时,显然是由一些“较小的x”得到的,故直接暴力枚举较小的x得到较小的n
4.当n比较大时,仍然是要尽可能多的放9,但是第一位不确定,最后一位也不确定,且倒数第二位可能为8,这个8加着加着就可能变为9,可以凑出一些特殊的数。也是采用暴力枚举

由于分类比较多,枚举范围也被缩小了很多,不存在超时的可能
比较稳健。思路也不是很混乱

typedef pair<ll,ll> P;
map<P,ll> M;
P tmp;
int t;
ll solve(ll x){ll res=0;while(x>0){res+=x%10;x/=10;}return res;}
ll qpow(ll a,ll b){ll res=1;while(b){if (b&1)res=res*a;b>>=1;a*=a;}return res;}
int main()
{
    for (ll i=0;i<2000;i++)
    {
        for (ll j=0;j<=9;j++)
        {
            ll ans=0;
            for (ll k=0;k<=j;k++)ans+=solve(i+k);
            tmp.first=ans,tmp.second=j;
            if (M[tmp]==0)M[tmp]=i;
            else M[tmp]=min(M[tmp],i);
        }
    }
    for (ll i=0;i<=9;i++)
    {
        for (ll j=0;j<=9;j++)
        {
            for (ll l=0;l<=1;l++)
            {
                for (ll k=0;k<=9;k++)
                {
                    ll sum=k+j*qpow(10,i+l+1)+8*10*l;
                    for (ll p=1;p<=i;p++)sum+=9*qpow(10,p+l);
                    for (ll q=0;q<=9;q++)
                    {
                        ll ans=0;
                        for (ll c=0;c<=q;c++)ans+=solve(sum+c);
                        tmp.first=ans,tmp.second=q;
                        if (M[tmp]==0)M[tmp]=sum;
                        else M[tmp]=min(M[tmp],sum);
                    }
                }
            }
        }
    }
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld",&tmp.first,&tmp.second);
        if ((tmp.second+1)*tmp.second/2==tmp.first)W(0);
        else if (tmp.second==0)
        {
            int num=tmp.first/9;
            if (tmp.first%9!=0)printf("%d",tmp.first%9);
            repp(i,0,num)printf("%d",9);
            puts("");
        }
        else if (M[tmp]==0)W(-1);
        else WW(M[tmp]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值