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;
}