简单的卡常数【OI缩水版】

举报
小哈里 发表于 2022/05/11 00:39:14 2022/05/11
【摘要】 一、为什么要卡常数? OI中数据结构与常数优化关系很大的如果你常数好可以暴力过数据结构题啦~如果你常数不好即使复杂度一样也会被出题人卡~ 二、常用的卡常数方法 1、卡IO(输入输出) 比较...

一、为什么要卡常数?

这里写图片描述

  • OI中数据结构与常数优化关系很大的
  • 如果你常数好可以暴力过数据结构题啦~
  • 如果你常数不好即使复杂度一样也会被出题人卡~

二、常用的卡常数方法

1、卡IO(输入输出)

比较简单的写法:

int readint(){
    int op=1,x=0;  char ch=getchar();
    while(ch<'0' || ch>'9'){if(ch=='-')op=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return op*x;
}
void outint(int x){
    if(x<0){putchar('-');x=-x;}
    if(x>9)outint(x/10);
    putchar(x%10+'0');
}
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

比较奇怪的写法

mmap
  
 
  • 1

2、卡编译

2.1 C++内联函数inline

由编译器在编译时会在主程序中把函数的内容直接展开替换,减少了内存访问。(如果是递归可能会展开前几层的运算吧?)

int max(int a, int b){return a>b?a:b;}//原函数
inline int max(int a, int b){return a>b?a:b;}//前面直接加inline就好了。
  
 
  • 1
  • 2
2.2 CPU寄存器变量register

对于一些频繁使用的变量,可以声明时加上该关键字,运行时可能会把该变量放到CPU寄存器中,只是可能,不保证有效。特别是你变量多的时候,一般还是丢到内存里面的。
比较下面两段程序:

register int a=0;
for(register int i=1;i<=999999999;i++)a++;
  
 
  • 1
  • 2
int a=0;
for(int i=1;i<=999999999;i++)a++;
  
 
  • 1
  • 2

优化:0.2826 second
不优化:1.944 second


3、卡计算

3.1 取模优化
占坑待填,据说 https://loj.ac/article/327
  
 
  • 1
3.2 加法优化

++i代替i++
1. 后置++需要保存临时变量以返回之前的值,在 STL 中非常慢。
2. 事实上,int的后置++ 在实测中也比前置++ 慢0.5倍左右(UOJ 上自定义测试)

3.3 数组优化

1、不要开bool,所有bool改成char,int是最快的(原因不明)。
2、在最大值50000*50000的时候用unsigned代替long long
3、对于多维数组,用到乘法优化寻址

// Code A
for(i=1;i<=n;i++)
    ans+=A[x][y][z][i];
// Code B
int *p=A[x][y][z];
for(i=1;i<=n;i++)
    ans+=*(p+i);
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
3.4 判断优化

if()else语句比()?():()语句要慢,逗号运算符比分号运算符要快。

3.5 结构优化

1.如果你要经常调用a[x],b[x],c[x]这样的数组,把她们写在同一个结构体里面会变快一些,比如f[x].a, f[x].b, f[x].c
2.指针比下标快。

3.7 欢迎补充

4、卡算法/预处理

4.1 STL优化

STL非常慢,可以手写。

4.2 倍增优化

倍增表小的开前面——寻址会变快很多

4.3 Floyd初始化
for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
        gra[i][j]=inf
for(int i=1;i<=b;i++)
    gra[i][i]=0
  
 
  • 1
  • 2
  • 3
  • 4
  • 5

是比

for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    {
        if(i==j) gra[i][j]=0;
        else gra[i][j]=inf
    }    
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

快80%以上的,,因为要每次去比较。

4.4 循环展开

自己感受。。。

void Init_Array(int *dest, int n)
{
    int i;
    for(i = 0; i < n; i++)
        dest[i] = 0;
}
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
void Init_Array(int *dest, int n)
{
    int i;
    int limit = n - 3;
    for(i = 0; i < limit; i+= 4)//每次迭代处理4个元素
    {
        dest[i] = 0;
        dest[i + 1] = 0;
        dest[i + 2] = 0;
        dest[i + 3] = 0;
    }
    for(; i < n; i++)//将剩余未处理的元素再依次初始化
        dest[i] = 0;
}
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
4.5 占坑待填。

文章来源: gwj1314.blog.csdn.net,作者:小哈里,版权归原作者所有,如需转载,请联系作者。

原文链接:gwj1314.blog.csdn.net/article/details/79946680

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。