LuoguP1557 Kruscal的加法 题解
题目Link
就是这道题,做了我整整一天!
看到题目,首先想到的就是:就这?就这一道大水题也能是绿?然后十分钟写完代码,提交……
果不其然,绿题不是白绿的,看了一眼数据和讨论,又得写高精了……
先附上非高精代码:
#include<cstring>
#include<cstdio>
#include<iostream>
#include<cmath>
#define LL long long
using namespace std;
LL now;
LL tim;
char s[10000];
int k;
LL ans=0;
int main()
{
cin>>s;
for(int i=0;i<strlen(s);i)
{
k=1;
if(s[i]=='+')
{
k=1;
if(s[i+1]=='+')
{
tim=0;
while(s[i]=='+')
i++,tim++;i--;
}
i++;
}
if(s[i]=='-')
{
k=0;
if(s[i+1]=='-')
{
tim=0;
while(s[i]=='-')
i++,tim++;i--;
}
i++;
}
if(s[i]=='('){
i++;
tim=0;
while(s[i]>='0'&&s[i]<='9'){
tim=tim*10+s[i]-'0';
i++;
}
i++;
}
now=0;
while(s[i]>='0'&&s[i]<='9'){
now=now*10+s[i]-'0';
i++;
}
if(tim==0) tim=1;
if(k==1){
ans+=tim*now;
}
else{
ans-=tim*now;
}
tim=0;
}
printf("%lld\n",ans);
return 0;
}
从这份代码可以看出,对于输入字符串是以 ++a
或 +(n)a
的类型为一个板块输入并进行运算, tim
存入 +/-
的个数或者括号内的数字,代表乘数, now
代表 +/-
或括号后的数字,即代表被乘数,之后将 tim
与 now
相乘加入 ans
即可。
#include<cstring>
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
char s[20005];
int now[20005];
int t=0;
int tim;
int timm[20005];
int tt=0;
int k;
int ans[20005];
int c[20005];
int nb=0;
void w1(int m)// 加法运算
{
for(int i=1;i<=max(m,ans[0]);i++)
{
ans[i]=ans[i]+c[i];
ans[i+1]+=ans[i]/10;
ans[i]=ans[i]%10;
}ans[0]=max(m,ans[0]);
if(ans[max(m,ans[0])+1]) ans[0]++;
}
void w2(int m)// 减法运算
{
if(ans[0]<m||ans[0]==m&&ans[ans[0]]<c[m]||ans[0]==m&&ans[ans[0]]==c[m]&&ans[ans[0]-1]<c[m-1]||ans[0]==m&&ans[ans[0]]==c[m]&&ans[ans[0]-1]==c[m-1]&&ans[ans[0]-2]<c[m-2]) //暴力地判断减数和被减数的大小,下同;
{
ans[10000]=1;
for(int i=1;i<=max(m,ans[0]);i++)
{
c[i]-=ans[i];
if(c[i]<0){
c[i]+=10;
c[i+1]--;
}
}
ans[0]=max(m,ans[0]);
for(int i=1;i<=ans[0];i++){
ans[i]=c[i];
}
}
else
for(int i=1;i<=max(m,ans[0]);i++)
{
ans[i]-=c[i];
if(ans[i]<0){
ans[i]+=10;
ans[i+1]--;
}
}
}
void work1() // +++a的情况
{
memset(c,0,sizeof(c));
int m=t;
for(int i=1;i<=m;i++)
{
c[i]+=now[i]*tim;
c[i+1]+=c[i]/10;
c[i]=c[i]%10;
}
m++;
while(c[m]!=0)
{
c[m+1]=c[m]/10;
c[m]=c[m]%10;
m++;
}m--;
while(c[m]==0) m--;
if(k==1)
{
if(ans[10000]==1){
int flag=0;
if(ans[0]<m||ans[0]==m&&ans[ans[0]]<c[m]||ans[0]==m&&ans[ans[0]]==c[m]&&ans[ans[0]-1]<c[m-1]||ans[0]==m&&ans[ans[0]]==c[m]&&ans[ans[0]-1]==c[m-1]&&ans[ans[0]-2]<c[m-2])
flag=1;
w2(m);
if(flag==1) ans[10000]=0;
}
else
w1(m);
}
if(k==0)
{
if(ans[10000]==1){
w1(m);
}
else
w2(m);
}
while(ans[ans[0]]==0) ans[0]--;
}
void work2() // +(n)a 的情况
{
memset(c,0,sizeof(c));
for(int i=1;i<=t;i++)
for(int j=1;j<=tt;j++)
{
c[i+j-1]+=now[i]*timm[j];
}
for(int i=1;i<=t+tt;i++)
{
c[i+1]+=c[i]/10;
c[i]=c[i]%10;
}
int m=t+tt+1;
while(c[m]!=0)
{
c[m+1]=c[m]/10;
c[m]=c[m]%10;
m++;
}m--;
while(c[m]==0) m--;
if(k==1)
{
if(ans[10000]==1){
int flag=0;
if(ans[0]<m||ans[0]==m&&ans[ans[0]]<c[m]||ans[0]==m&&ans[ans[0]]==c[m]&&ans[ans[0]-1]<c[m-1]||ans[0]==m&&ans[ans[0]]==c[m]&&ans[ans[0]-1]==c[m-1]&&ans[ans[0]-2]<c[m-2])
flag=1;
w2(m);
if(flag==1) ans[10000]=0;
}
else{
w1(m);
}
}
if(k==0)
{
if(ans[10000]==1){
w1(m);
}
else
w2(m);
}
while(ans[ans[0]]==0) ans[0]--;
}
int main()
{
cin>>s;
for(int i=0;i<strlen(s);i)
{
k=1;
tim=0;
if(s[i]=='+') //输入加号及个数
{
k=1;
if(s[i+1]=='+')
{
tim=0;
while(s[i]=='+')
i++,tim++;i--;
}
i++;
}
if(s[i]=='-') //输入减号及个数
{
k=0;
if(s[i+1]=='-')
{
tim=0;
while(s[i]=='-')
i++,tim++;i--; //由于n<=2000,故在这种情况时,tim<=2000,直接用int存即可;
}
i++;
}
tt=0;
if(s[i]=='('){ //输入乘数
i++;
while(s[i]>='0'&&s[i]<='9'){
i++;
}i--;
while(s[i]>='0'&&s[i]<='9'){
timm[++tt]=s[i]-'0';
i--;
}i++;
while(s[i]>='0'&&s[i]<='9'){
i++;
}
i++;
}
while(s[i]>='0'&&s[i]<='9'){ //输入被乘数
i++;
}i--;
t=0;
while(s[i]>='0'&&s[i]<='9'){
now[++t]=s[i]-'0';
i--;
}i++;
while(s[i]>='0'&&s[i]<='9'){
i++;
}
if(tim==0&&tt==0) tim++;
if(tim){ //根据不同输入类型,进行不同运算
work1();
}
else{
work2();
}
}
while(ans[ans[0]]==0) ans[0]--;//ans[0]代表答案长度
if(ans[0]<1) ans[0]=1; //答案等于0时,ans[0]会减为0,进行特判;
if(ans[0]==1&&ans[1]==0){ //答案等于0时,不能输出-0,直接进行特判;
printf("0\n");
return 0;
}
if(ans[10000]==1) printf("-");
for(int i=ans[0];i>=1;i--)
printf("%d",ans[i]);
printf("\n");
return 0;
}
再来看这份AC代码,输入与上面非高精代码相同,把运算换成高精,但多了亿点点细节。
- 首先,要把数字作为一个数组输入,为了保证数组顺序,先让
i
跑到下一个非数字字符,再从后往前跑,把数字存入,然后再让i
跑回去准备下一次的读取; - 其次,高精运算涉及到负数,用
ans[10000]
来存储当前得数的正负,0
代表正,1
代表负,在进行加减运算时,通过判断当前得数的正负,巧妙地把加减运算互相转化; - 最后,要注意输出时,要把得数前多余的
0
删掉,同时不存在-0
,要进行特判;
希望管理通过QwQ
LuoguP1557 Kruscal的加法 题解的更多相关文章
- LuoguB2104 矩阵加法 题解
Content 给定两个 \(n\times m\) 的矩阵 \(A,B\),求 \(C=A+B\). 数据范围:\(1\leqslant n,m\leqslant 100\). Solution 我 ...
- BZOJ5321 & 洛谷4064 & LOJ2274:[JXOI2017]加法——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5321 https://www.luogu.org/problemnew/show/P4064 ht ...
- Challenge & Growth —— 从这里开始
做有挑战的事情,就从这里开始. 忘记这本书现在在哪儿了,以前还以为能祖祖辈辈留传,现在只能借助 Nowcoder 了.Now coder,Forever thinker. 想以自以为最优美的 code ...
- PAT(乙级)2020年春季考试
比赛链接:https://pintia.cn/market/item/1287964475579875328 7-1 对称日 题解 模拟,注意年月日不足位在前面补零. 代码 #include < ...
- 【题解】洛谷P1967 [NOIP2013TG] 货车运输(LCA+kruscal重构树)
洛谷P1967:https://www.luogu.org/problemnew/show/P1967 思路 感觉2013年D1T3并不是非常难 但是蒟蒻还是WA了一次 从题目描述中看出每个点之间有许 ...
- 力扣(LeetCode)整数形式的整数加法 个人题解
对于非负整数 X 而言,X 的数组形式是每位数字按从左到右的顺序形成的数组.例如,如果 X = 1231,那么其数组形式为 [1,2,3,1]. 给定非负整数 X 的数组形式 A,返回整数 X+K 的 ...
- PAT甲题题解-1023. Have Fun with Numbers (20)-大数加法
和1024一样都是大数据的题,因为位数最多要20位,long long最多19位给一个num,求sum=num+num问sum包含的数字,是否是num的一个排列,即数字都一样,只是顺序不同罢了. #i ...
- UNR #1 题解
A. 争夺圣杯 还是想说一下,这题是原题啊...想做的人可以戳codechef上的MTMXSUM(懒得贴链接了,套了个壳,不过正常人应该都能看得出来) 显然异或输出没什么奇怪的性质... 考虑一个元素 ...
- JSOI Round 2题解
强行一波题解骗一个访问量好了... http://blog.csdn.net/yanqval/article/details/51457302 http://absi2011.is-programme ...
随机推荐
- Git修改历史commit的author信息
前言 "嘀嗒嘀嗒",抬头看向墙上的钟表,此时已是凌晨1点.小明终于把Go语言圣经第二章的笔记写完,保存commit,提交,然后睡觉. 额,等等,不对,小明发现他用的是公司的git账 ...
- linux》centos6.1.环境下发送邮件设置
转自https://blog.csdn.net/bodybo/article/details/80817968 一. Sendmail安装 在CentOS下,sendmail一般默认是随操作系统一起安 ...
- Bing每日壁纸的RESTful接口实现
0x00 存在意义 权且当作Docker打包的练习. 显然可以通过构造请求获得每天的壁纸,但是如果想要优雅地在其它地方使用这一网络资源,封装一个RESTful API将会保证整洁美观,在编写CSS等场 ...
- linux centos7 移动文件到指定目录
2021-08-26 在 centos7 环境下怎么移动一个文件到其他的目录下呢? 使用命令 mv 文件名 指定目录 即可完成该操作. 那么怎么将一个文件夹下的内容移动到另一个文件夹下呢?比如有时 ...
- 整理之Activity
基础 生命周期 执行层次 进 退 创建与销毁 onCreate() onDestroy() 是否可见 onStart() onStop() 是否在前台(可交互) onResume() onPause( ...
- Leaflet 操作OSM(OpenStreetMap) 设置地图style
Leaflet是一个开源的地图操作库,其中mapbox是其一个插件,这个插件可以自定义想要的地图格式.https://www.mapbox.com/mapbox-gl-js/api/这是其官网地址. ...
- Linux系统的内核编译
<1>给虚拟机分配2048M内存 <2>配置高可用yum源 <3>下载软件 <1>安装内核源码包 根据依赖性提示,安装对应的包 下载并安装软件包(3个) ...
- 如何实现 Android 短视频跨页面的流畅续播?
在一切皆可视频化的今天,短视频内容作为移动端产品新的促活点,受到了越来越多的重视与投入,同时短视频也是增加用户粘性.增加用户停留时长的一把利器.那么如何快速实现移动端短视频功能呢?前两篇我们介绍了盒马 ...
- python 加速运算
原文链接:https://blog.csdn.net/qq_27009517/article/details/103805099 一.加速查找 1.用set而非list import time dat ...
- ubuntu安装glusterFS
以2台服务器为例: node1: 172.18.1.10 node2: 172.18.1.20 1) 修改主机名,修改hosts文件添加IP地址映射 hostname node1/node2vim / ...