训练总结之各种各样的错

  • ull unsigned long long

  • long long 和 double/long double运算会出错,long long隐式转换成double不存在,应避免。

  • map的count(),防爆空间
    大数据用map存下标时,判断是否存在用count(),不然还是会爆空间。

  • memset小心使用,防T【可以fill,或者手动写循环清空】

  • double:%lf
    long double:%Lf


  • 空间大小(单位:B,字节)及数据范围
    【爆空间真的可怕】
    在这里插入图片描述在这里插入图片描述

码住

这部分一直很困惑,先很杂地把我觉得有用的堆这里【待整理

四舍五入
  1. printf
    printf("%.1f",a)
  2. round函数【浮点数变整数了】
double round(double r){
    return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
}

举例round结果:

round(0.1) = 0
round(-0.1) = -0
round(-0.9) = -1
round(12.23)=12
round(12.63)=13
round(-12.23)=-12
round(-12.63)=-13
  1. 保留一位小数+0.05,保留2位小数+0.005,保留3位小数+0.0005
    printf("%.1f %.2f %.3f\n", a+0.05, a+0.005, a+0.0005);

一个浮点数乘以100再加上0.5再使用floor函数后除以100后,会得到四舍五入的保留小数点后两位的数。
【floor函数其实相当于对浮点数强制转换成int类型】
浮点数a扩大10^(k)次转成整数,则:int c=(int)a*qpow(10,k)+0.5.


在这里插入图片描述printf("%.8d\n",1000); //不足指定宽度补前导0,效果等同于%06d
printf("%.8f\n",1000.123456789);//超过精度,截断
printf("%.8f\n",1000.123456); //不足精度,补后置0
printf("%.8g\n",1000.123456); //最大有效数字为8位
printf("%.8s\n",“abcdefghij”); //超过指定长度截断
输出:
00001000
1000.12345679
1000.12345600
1000.1235
abcdefgh


  • 精度问题的产生主要是因为计算机用2进制存数,因而浮点数都难免带有误差,比如0.9虽然只有一位小数,但转成2进制是无限循环小数0.1110011001100110011…。
    所以在计算机的本身储存就有误差的浮点数加加减减得出来的结果,和十进制中的无误差的实数加加减减再转成2进制的结果,是有误差的,误差一般很小。

  • 精度问题esp如何确定
    取esp为极小值,如1e-6
    举个例子http://codeforces.com/gym/102500/problem/E
    ac代码
    ac代码
    wa6代码
    wa6
    区别在于浮点数的比较,应当是介于(-esp,esp)方为相等。脑子当时瓦特了。。。
    【平时浮点数比较都没注意这些,都是直接比较,导致这不行那wa的】【cmp码住】
    【要求保留两位小数的话,esp必须小于等于1e-2】
    【此题具体信息及ac代码见:https://blog.csdn.net/qq_42819250/article/details/106042085

  • 高精度运算:https://www.jianshu.com/p/fb31d5115c6e


  • 500 * 500 * 500的输入,用cin,T过。
  • 数组大小一定要比数据数量还要大,不然可能会wa。
  • 查并集找爸爸那个函数,T的时候往往是那里写错了。
int findfa(int x){
	if(fa[x]==x)return fa[x];
	return fa[x]=findfa(fa[x]);
	//return findfa(fa[x]);换这个会T
}
  • 超时也有可能是数组空间开太小了。

  • 注意数据范围,题目往往会因为负数的加入而复杂化因为可能就需要分类讨论了,且!下标不可负。[试试可不可以离散化]。

  • 输入的时候出错导致尚未全部输入答案已经输出,如若有输入字符串或字符的话,记得getchar()。记得getline()用法。

  • 数据多时,不要用vector,会超时(比如牛客暑期训练第五场第二题)。
    二维数组尽量不要用map或vector存,会超时。
    map的count()本身也有一定复杂度。
    使用vector超时实例https://blog.csdn.net/qq_42819250/article/details/106306515

  • 爆空间MLE发生在第2或2以上的test,且使用了vector动态数组,那么往往申请的空间是不会超出限制的,问题出在vector。代码运行过程中动态存入vector的数据肯定太多了。要么题目没读清,要么想岔了。

  • 看清题目要求的是 “1<i,j<n” 还是"1<i<j<n"

  • map不等于数组!!!他里面是按<排序了的
    几次用map当数组记录答案莫名其妙出错过,终于找到罪魁祸首

  • 用map超时了,但是可以用unordered_map过
    该题目:https://ac.nowcoder.com/acm/contest/5667/B
    AC代码:

int sgn(double x){
    if(fabs(x) < eps)return 0;
    if(x < 0)return -1;
    else return 1;
}
struct Point{
    double x,y;
    Point(){}
    Point(double _x,double _y){
        x = _x;y = _y;
    }
    Point operator -(const Point &b)const{
        return Point(x - b.x,y - b.y);
    }
    double operator ^(const Point &b)const{
        return x*b.y - y*b.x;
    }
    double operator *(const Point &b)const{
        return x*b.x + y*b.y;
    }
    void transXY(double B){
        double tx = x,ty = y;
        x = tx*cos(B) - ty*sin(B);
        y = tx*sin(B) + ty*cos(B);
    }
};
Point waixin(Point a,Point b,Point c){
    double a1 = b.x - a.x, b1 = b.y - a.y, c1 = (a1*a1 + b1*b1)/2;
    double a2 = c.x - a.x, b2 = c.y - a.y, c2 = (a2*a2 + b2*b2)/2;
    double d = a1*b2 - a2*b1;
    return Point(a.x + (c1*b2 - c2*b1)/d, a.y + (a1*c2 -a2*c1)/d);
}
double x[maxn],y[maxn];
struct pair_hash{
    template<class T1, class T2>
    std::size_t operator() (const std::pair<T1, T2>& p) const{
        auto h1 = std::hash<T1>{}(p.first);
        auto h2 = std::hash<T2>{}(p.second);
        return h1 ^ h2;
    }
};
unordered_map<pair<double,double>,int,pair_hash> mp;
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        scanf("%lf%lf",&x[i],&y[i]);
    }
    if(n<=2){
        printf("%d\n",n);
        return 0;
    }
    Point O(0.0,0.0);
    int ans=0;
    for(int i=1;i<=n;i++){
        mp.clear();
        for(int j=1;j<=n;j++){
            if(sgn(x[i]*y[j]-x[j]*y[i])==0)continue;
            Point tmp=waixin(O,Point(x[i],y[i]),Point(x[j],y[j]));
            mp[pdd(tmp.x,tmp.y)]++;
            ans=max(ans,mp[pdd(tmp.x,tmp.y)]);
        }
    }
    cout<<ans+1<<"\n";
}

T:


int sgn(double x){
    if(fabs(x) < eps)return 0;
    if(x < 0)return -1;
    else return 1;
}
struct Point{
    double x,y;
    Point(){}
    Point(double _x,double _y){
        x = _x;y = _y;
    }
    Point operator -(const Point &b)const{
        return Point(x - b.x,y - b.y);
    }
    double operator ^(const Point &b)const{
        return x*b.y - y*b.x;
    }
    double operator *(const Point &b)const{
        return x*b.x + y*b.y;
    }
};
Point waixin(Point a,Point b,Point c){
    double a1 = b.x - a.x, b1 = b.y - a.y, c1 = (a1*a1 + b1*b1)/2;
    double a2 = c.x - a.x, b2 = c.y - a.y, c2 = (a2*a2 + b2*b2)/2;
    double d = a1*b2 - a2*b1;
    return Point(a.x + (c1*b2 - c2*b1)/d, a.y + (a1*c2 -a2*c1)/d);
}
double x[maxn],y[maxn];
map<pdd,int>mp;
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        scanf("%lf%lf",&x[i],&y[i]);
    }
    if(n<=2){
        printf("%d\n",n);
        return 0;
    }
    Point O(0.0,0.0);
    int ans=0;
    for(int i=1;i<=n;i++){
        mp.clear();
        for(int j=1;j<=n;j++){
            if(sgn(x[i]*y[j]-x[j]*y[i])==0)continue;
            Point tmp=waixin(O,Point(x[i],y[i]),Point(x[j],y[j]));
            mp[pdd(tmp.x,tmp.y)]++;
            ans=max(ans,mp[pdd(tmp.x,tmp.y)]);
        }
    }
    cout<<ans+1<<"\n";
}
  • 离散化尽量别用map,直接lower_bound !【T过】https://ac.nowcoder.com/acm/contest/5673/I

  • strlen(s)返回值是unsigned类型,所以别和负数比较大小。【这个坑点要小心避开】
    在看kmp的时候发现的,找半天才把目光放在strlen上。

小测试:

int main(){
	unsigned int k1=1;
	int k2=k1;//将无符号数转成有符号数
	int i=-1;
	//在无符号数中,-1是最大的那个数。
	//在这里由于是int和unsigned int间比较大小,故而强制转换
	cout<<(i<k1)<<"\n";
	cout<<(i<k2)<<"\n";
}
//输出
//0
//1

int main(){
	unsigned int k1=-1;
	cout<<k1<<"\n";
}
//输出
//4294967295

https://www.cnblogs.com/Erma/p/7404838.html
https://blog.csdn.net/JX_Cesare/article/details/81153410

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值