打FFT时中发现的卡常技巧

题目:洛谷P1919 A*B Problem 加强版

我的代码完全借鉴boshi,然而他380ms我880ms。。。于是我通过彻底的卡(chao)常(dai)数(ma)成功优化到了380ms,都是改了一些等效写法,所以我决定把我发现的技巧贴出来,说不定以后用得到。。。如果你有什么卡常技巧也请告诉我QwQ

1.加register

这个不必多说了吧,卡常基本操作之一,但是貌似加多了也会慢

2.运算符重载时加上取地址符

本来是这样:

class cp
{
public:
    double real,imag;
    cp operator+(const cp aa)
    {return (cp){real+aa.real,imag+aa.imag};}
    cp operator-(const cp aa)
    {return (cp){real-aa.real,imag-aa.imag};}
    cp operator*(const cp aa)
    {return (cp){real*aa.real-imag*aa.imag,real*aa.imag+imag*aa.real};}
};

改成了这样:

class cp
{
public:
    double real,imag;
    cp operator+(const cp& aa)
    {return (cp){real+aa.real,imag+aa.imag};}
    cp operator-(const cp& aa)
    {return (cp){real-aa.real,imag-aa.imag};}
    cp operator*(const cp& aa)
    {return (cp){real*aa.real-imag*aa.imag,real*aa.imag+imag*aa.real};}
};

原因未知,但快了不少。

3.不要重载等号

如果你写了这样的函数:

cp& operator=(const cp& aa)
{if(this!=&aa){real=aa.real,imag=aa.imag;}return *this}

除非你用等号干一些特殊的事,否则去掉吧。编译器会自动重载等号,而且绝对要更快。

4.去掉多余的构造函数

一开始我是这么写的:

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));

改成了这样后:

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)};

就变快了,看来构造函数耗时还是很大的,尤其是当你要设一组变量的时候。


所以说,C++这玩意真的玄学=。=如果你有别的卡常技巧请务必告诉我QwQ

posted @ 2018-07-22 16:48  sclbgw7  阅读(527)  评论(0编辑  收藏  举报