c++卡常技巧-164

常卡,乃诺骗分最重要的秘诀,这里总结了常卡常(来自一些大牛的博客)

持续更新中

目录

正文 

一、位置

1.如果上一个2的倍数,可以改用左移(Left Shift)加速300%

x = x * 2;
x = x * 64;

改为:

x = x << 1; 
x = x << 6; 

2. 如果除上一个 2 倍数的成绩,可以改用右移加速运动 350%

x = x / 2;
x = x / 64;

改为:

x = x >> 1; 
x = x >> 6; 

3. 会员转加速 10%

x = int(1.232)

改为:

x = 1.232 >> 0;

4.交换两个(swap),使用XOR可以加速20%

int a,b,c;
c = b;
b = a;
a = c;

改为:

a = a ^ b;
b = a ^ b;
a = a ^ b;

5. 正负号转换,可以加入300%

·cpp a = -a; ···改为:

i = ~i + 1; // NOT 写法
i = (i ^ -1) + 1; // XOR 写法

6. 取余数,如果数为 2 的倍数,可利用并加速除数 600%

x=131%4;
x=x&(4-1);

7. 使用 AND 考试是否必须为 2 的倍数,可以加速 600%

if(1%2==0)
if(i&1==0) 

8. 加速加速 Math.abs 600% 的写法1,写法2 又比写法1 20%

//写法1
i = x < 0 ? -x : x;
//写法2
i = (x ^ (x >> 31)) - (x >> 31);
//或者
i=x^(~(x>>31)+1)+(x>>31);

9.x++ 可以用位解决

x++;

改为:

x=-~x;

10.求2的n次方(当然快速提升)

x=pow(2,y);
x=1<<y;

二、循环

1.i++与++i,++i来,一下是c++源码

++i

INT   INT::operator++()   
{   
        *this=*this+1;   
        return   *this;   
} 
const INT INT::operator  ++(int)   
  {   
            INT   oldvalue=*this;   
            *this=*this+1;   
            return   oldvalue   
  }  

所以,审核

for(int i=1;i<=n;i++){
}

改为:

for(int i=1;i<=n;++i){
}

2.把循环给展开试,速度会快很多

情况1(循环执行多条语句):

?
1
2
for(int i=1;i<=n;++i)
    a=1,b=1;

改为:

?
1
2
for(int i=1;i<=n;++i)a=1;
for(int i=1;i<=n;++i)b=1;

情况2(循环执行单条语句):

?
1
2
3
4
5
6
7
8
9
double sum(double *a,int n)
{
    double s=0;
    for(int i=1;i<=n;i++)
    {
        s+=a[i];
    }
    return s;
}

改为:

?
1
2
3
4
5
6
7
8
9
10
11
12
double sum(double *a,int n)
{
    double s0=0,s1=0,s2=0,s3=0;
    for(int i=1;i<=n;i+=4)
    {
        s0+=a[i];
        s1+=a[i+1];
        s2+=a[i+2];
        s3+=a[i+3];
    }
    return s0+s1+s2+s3;
}

3.++i 原则上可以更优化(使用位自由)

1
2
3
for(int i=1;i<=n;++i)
{
}

改为:

1
2
3
for(int i=1;i<=n;i=-~i)
{
}

4. 5. 在循环中广泛进行的同时,要提高循环效率,从编入代码可以高度理解,在高度理解6. 6. 33. 节前,可以在节时,将节前,将,while转换为do...while

?
1
2
3
4
for(;;){
}
while(){
}

改为:

?
1
2
do{
}while()

if() else语句比()?():()语句要慢

?
1
2
if()
else

改为:

?
1
()?():()

三、属性与变量

1.在int前加寄存器

?
1
int a;

改为:

?
1
register int a;

2. 异常语句

?
1
int a=1;

改为:

?
1
int a(1);

3.能不用变量就不用,转而用特征

?
1
2
3
4
5
6
7
8
9
10
11
12
13
//10s
int p=10;
int main()
{
    open("orzzjt");
    int a;
    scanf("%d",&a);
    int i;
    for(i=1;i<=1000000000;i++)
        a=(a*a+10)%p;
    printf("%d\n",a);
    return 0;
}

改为:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
//6s
const int p=10;
int main()
{
    open("orzzjt");
    int a;
    scanf("%d",&a);
    int i;
    for(i=1;i<=1000000000;i++)
        a=(a*a+10)%p;
    printf("%d\n",a);
    return 0;
}

4.多维菜请把大的放前面

?
1
int dp[2][10][100000];

改为:

?
1
int dp[100000][10][2];

5.speed bool慢于char慢于int

所以在不考虑空间的情况下,尽量使用int而不是bool

?
1
bool a[10000];

改为:

?
1
int a[10000];

四.函数

1.在函数前加inline可以魔梯

?
1
2
3
4
int x(int a,int b)
{
    return a+b;
}

改为:

?
1
2
3
4
inline int x(int a,int b)
{
    return a+b;
}

五、输入输出

1.读入优化

?
1
scanf("%d",&a);

改为:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
inline int read()
{
    int x,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
        {
            f=-1;
        }
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }
    return x*f;
}

2.字符串输入输出能用char就别用string

?
1
2
3
string s;
cin>>s;
cout<<s;

改为:

?
1
2
3
char c[100];
scanf("%s",c);
printf("%s",c);

3.和输入一样,输出也有快写

?
1
printf("%d",x);

改为:

?
1
2
3
4
5
6
7
8
9
10
11
inline void print(int x)
{
    int ot;
    while(x)
    {
        ot=x%10;
        putchar(ot+'0');
        x/=10;
    }
    return ;
}

六、搜索

1.当dfs快速直接定位时,停止搜索,输出当前最优解

模板:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<ctime>
#include<cstdlib>
#include<iostream>
using namespace std;
double t;
const double CLOCKS_PER_SECOND=((clock_t)1000);//定义常量
void dfs()
{
    cout<<1;
    if(1000*(clock()-t)>=900*CLOCKS_PER_SECOND)//即将超过1000ms时输出答案并结束程序,防止超时
    {
        /*输出答案*/
        exit(0);//退出
    }else
    dfs();//否则继续搜索
}
int main(){
    t=clock();//记录开始时间
    dfs();
    return 0;
}

七、习题

1.取模

?
1
2
3
int mod(int x,int y){
    return x%y;
}

改为:

?
1
2
3
int mod(int x, int y){
    return x - y * (x / y);
}

然而可以做到:

?
1
2
3
int mod(int x,int y){
   x=x&(1<<y-1);
}

2.加法取模

?
1
ll add(ll a,ll b){return (a+b)%p;}

改为:

?
1
ll add(ll a,ll b){a+=b;return (a>=b?a-=p:0),a;}

减法同理

3地址还是重载时(不知道是c++)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
class cp
{
public:
    double real,imag;
    cp(double x=0.0,double y=0.0)
    {real=x,imag=y;}
    cp operator+(const cp aa)const
    {return cp(real+aa.real,imag+aa.imag);}
    //......
};
 
//in FFT()
cp wn(cos(pi/i),f*sin(pi/i));

改为:

?
1
2
3
4
5
6
7
8
9
10
11
class cp
{
public:
    double real,imag;
    cp operator+(const cp aa)
    {return (cp){real+aa.real,imag+aa.imag};}
    //......
};
 
//in FFT()
cp wn=(cp){cos(pi/i),f*sin(pi/i)};
  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值