P6581 远大目标 题解
0. 题目link https://www.luogu.com.cn/problem/P6581
1. 题面分析
2. 做法
2.1 Python做法
2.2 C++做法
1. 题面分析
观察题目,通过绝对值的知识,我们对 (operatorname{sum}(A)) 的取值进行一个分析,易得(请自证):
sum(A)指满足条件的A的个数
[operatorname{sum}(A)=egin{cases}2*O-1(O>0)\0(Oleqslant0)end{cases}
]
所以,这道题只需要简单的计算就行了吗?
当我们看到Subtask 3的数据时,连ull也无能为力...
高精是必须的。
2.做法
高精度就是模拟你列竖式计算的过程 小学上过就行
如果不太懂,可以结合C++题解里的注释分析。
2.1 Python做法
说到高精度,你一定想到了Python。
毕竟Python自带高精度,可以偷懒水题
初学者应该都可以看懂。
代码:
a = int(input())
if a>0:
print(a*2-1)
else:
print(0)
2.2 C++做法
C++没有自带高精度,所以,手打吧!
本质是模拟进位,退位。
代码:
#include<bits/stdc++.h>//万能头
using namespace std;
int digit[30];//模拟数位的数组
int main(){
string s;
cin>>s;//由于读不了数字,读一个string
digit[0]=s.length();//个人习惯把长度放digit[0]里
int flag=0;//用来检测是否全都是0 P.S.:例如0000这种 但是数据貌似没有
for(int i=0;i<s.length();i++){//枚举0
if(s[i]!='0')flag=1;
}
if(flag==0){//如果是0,答案显然是0
cout<<0;
return 0;
}
if(s[0]=='-'){//负数也是0
cout<<0;
return 0;
}
for(int i=0;i<s.length();i++){
digit[s.length()-i]=s[i]-'0';//!注意,这里要倒着存,进位才方便
}
for(int i=1;i<=digit[0];i++){
digit[i]=digit[i]*2;//翻倍,实现O*2
}
for(int i=1;i<=digit[0];i++){//来实现进位
//为什么要分开?进位的时候进的1不然也会被*2
if(digit[i]>=10){
digit[i]-=10;
digit[i+1]+=1;
}
}
if(digit[digit[0]+1]==1)digit[0]++;//自己理解一下,看最高后面有没有进位,如果有,长度+1
digit[1]--;//实现2*O-1的-1
for(int i=1;i<=digit[0];i++){//防止-1的情况,借一位
if(digit[i]<0){
digit[i]+=10;
digit[i+1]-=1;
}
}
if(digit[digit[0]]==0)digit[0]--;//如果最高位退到了0,长度-1
for(int i=digit[0];i>=1;i--){
cout<<digit[i];//之前反着存储,所以要反着输出
}
return 0;
}