Codeforces Round #342 (Div. 2) A D题

B、C题较水就不写题解了(还是太懒了)。


A题

题目连接:Problem A


题意:

给你n元钱,你去买饮料,有两种饮料,一个是玻璃瓶的,一个是塑料瓶的。一瓶塑料瓶的饮料花费a元,而一瓶玻璃瓶的饮料需要b元,并且退回空的玻璃瓶还给你c元钱。

问你最多能买多少瓶饮料。取值范围:1<=n<=1e18 ,1<=a<=1e18  ,1<=c<b<=1e18。


题解:

我们分类讨论下,如果a<=b-c,肯定是买塑料瓶的会好点,因为买玻璃瓶的首先你要有b元才能买。

而a>b-c&&b>=n的情况下,我可以先买玻璃瓶的,并且利用剩下的钱买塑料瓶,而且我玻璃瓶每瓶实际花的是(b-c)元,所以买的会更多。


代码:

#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<vector>
#include<bitset>
#include<set>
#include<queue>
#include<stack>
#include<map>
#include<cstdlib>
#include<cmath>
#define PI 2*asin(1.0)
#define LL long long
#define pa pair<int,int>
#define pb push_back
#define clr(a,b) memset(a,b,sizeof(a))
#define lson lr<<1,l,mid
#define rson lr<<1|1,mid+1,r
#define bug(x) printf("%d++++++++++++++++++++%d\n",x,x)
const int  MOD = 1000000007;
const int N = 100+15;
const int maxn = 2e4 + 14;
const int INF = 1e17;
const int letter = 130;
const double pi=acos(-1.0);
const double eps=1e-10;
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
LL n,a,b,c;
int main(){
    scanf("%I64d%I64d%I64d%I64d",&n,&a,&b,&c);
    LL ans=0;
    if(b-c<a&&n>=b){
        ans = (n-b)/(b-c)+1;
        n-=ans*(b-c);
    }
    ans += n/a;
    printf("%I64d\n",ans);
    return 0;
}


D题

题目连接:Problem D


题意:

给你一个数n(1<=n<=1e100000)。找到一个数a,使得a翻转过来的数ar, a+ar=n。如果存在这样的a,输出a,如果不存在输出0。

例如:123+321=444


题解:

我们假设一个数的各个位为 a1 a2 a3 a4 a5,翻转过来为a5 a4 a3 a2 a1。再相加的话为 a1+a5   a2+a4  a3+a3  a4+a2  a1+a5。

我们发现这是一个“回文串”。但是由于加法的进制问题。导致数看起来并不是“回文串”。例如:2834+4382 = 7216 -> 6 11 11 6

所以我们要把它改成“回文串”。怎么改?

我们可以从头跟尾向中间靠。设两个指针 l,r,l从高位往中间指(1->mid),r从低位往高位指(n->mid),l,r是一起移动的。

假设数组b为"回文串"的数组,初值为原值。

假设b[l]==b[r]+10||b[l]==b[r]+11,是不是b[r]其实是大于10的,只是因为进制的问题而减小了10,b[r-1]要减一,b[r]要加上10。

然后如果b[l]-b[r]==1(前面的都已经处理完了)的话是不是因为进制的问题b[l]多了从b[l+1]来的1。所以b[l]--,b[l+1]+=10。

然后再判断b[l]是否等于b[r],不等于的话,说明不存在。

要注意几个特判:

1、处理完之后b[l],b[r]的取值范围为[0.18];

2、如果l==r(奇数长)判断b[l]是否是偶数,不是偶数也是不存在的;

3、b[l],b[r]的取值尽可能的相近,例如:b[l]=b[l]-(b[r]>>1),b[r]>>=1;

4、如果最高位为1且长度大于1,要注意 57+75=132这样情况,直接b数组的长度缩短一位,最高位再加上10就可以了。

(详情见代码)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<vector>
#include<bitset>
#include<set>
#include<queue>
#include<stack>
#include<map>
#include<cstdlib>
#include<cmath>
#define PI 2*asin(1.0)
#define LL long long
#define pb push_back
#define pa pair<int,int>
#define clr(a,b) memset(a,b,sizeof(a))
#define lson lr<<1,l,mid
#define rson lr<<1|1,mid+1,r
#define bug(x) printf("%d++++++++++++++++++++%d\n",x,x)
#define key_value ch[ch[root][1]][0]
const int  MOD = 1000000007;
const int N = 1e5+15;
const int maxn = 450;
const int letter = 130;
const int INF = 15000000;
const double pi=acos(-1.0);
const double eps=1e-8;
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
char a[N],ans[N];
int b[N],n;
bool solve(){
    ///928818
    for(int l=0,r=n-1;l<=r;l++,r--){
        if(b[l]==b[r]+10||b[l]==b[r]+11) {
            b[r-1]--,b[r]+=10;
        }
        if(b[l]-b[r]==1){
            b[l+1]+=10,b[l]--;
        }
        if(b[l]!=b[r]) return 0;
        if(b[l]<0||b[l]>18||b[r]<0||b[r]>18) return 0;
        if(l==r&&b[r]&1){
                return 0;
        }
        if(l!=r)b[l]=b[l]-(b[r]>>1),b[r]>>=1;
        else  b[r]>>=1;
     /*   for(int i=0;i<n;i++) printf("%d ",b[i]);
        printf("\n");*/
    }
    for(int i=0;i<n;i++) ans[i]=b[i]+'0';
    ans[n]='\0';
    if(ans[0]=='0') return 0;
    return 1;
}
int main(){
    scanf("%s",a);
    n=strlen(a);
    for(int i=0;i<n;i++) b[i]=a[i]-'0';
    if(solve()){
        printf("%s\n",ans);
    }
    else if(a[0]=='1'&&n>1){
        for(int i=0;i<n-1;i++) b[i]=a[i+1]-'0';
        b[0]+=10;
        n--;
        if(solve()) printf("%s\n",ans);
        else puts("0");
    }
    else puts("0");
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值