关于卡常

关于卡常

快读

普通快读

众所周知,字符串输入输出比数字快,于是就有了以下快读

namespace Q{
    il int rd(){
        ri int x=0,f=1;ri char c=getchar();
        while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0'&&c<='9') x=x*10+(c^48),c=getchar();
        return x*f;
    }
    il void wt(int x){
        if(x<0) x=-x,putchar('-');
        if(x>=10) wt(x/10);
        return putchar(x%10+48),void();
    }
} using namespace Q;

快快读~

一般情况下,上面的快读就够用了
但是如果只差一点就可以卡进去的话,可以考虑一下快快读(注意空间,可能会\(MLE\)

namespace Q{
    cs int IO=1<<25;
    char ibuf[IO],*is=ibuf+IO,*it=ibuf+IO;
    #define gc (is==it)?(it=(is=ibuf)+fread(ibuf,1,IO,stdin),(is==it)?EOF:*is++):*is++
    il int rd(){
        ri int x=0;ri bool f=0;ri char c=gc;
        while(!isdigit(c)) f|=(c==45),c=gc;
        while(isdigit(c)) x=x*10+(c^48),c=gc;
        return f?-x:x;
    }
    char out[IO],*itr=out;
    #define Flush() fwrite(out,1,itr-out,stdout),itr=out
    short a[35],tl;
    il void wt(int x,char lastchar=10){
        if(x<0) (*itr++)=45,x=-x;
        do a[++tl]=x%10,x/=10; while(x);
        while(tl) (*itr++)=a[tl--]+48;
        (*itr++)=lastchar,Flush();
    }
} 

快速取模

struct fastmod{
    typedef unsigned long long u64;
    typedef __uint128_t u128;

    int m;
    u64 b;

    fastmod(int m) : m(m), b(((u128)1 << 64) / m) {}
    int reduce(u64 a){
        u64 q = ((u128)a * b) >> 64;
        int r = a - q * m;
        return r < m ? r : r - m;
    }
} z(2);

当模数为\(mod\)时,先在程序开始调用\(z=fastmod(mod)\),之后要计算一个在\([0,2^{64})\)内的整数\(n\)\(mod\)取模的结果时调用\(z.reduce(n)\),其返回值即是\(n\)\(mod\)取模的结果

具体使用方法如下(还是快了很多的)

#include <bits/stdc++.h>

using namespace std;

int n, mod;

struct fastmod{
    typedef unsigned long long u64;
    typedef __uint128_t u128;

    int m;
    u64 b;

    fastmod(int m) : m(m), b(((u128)1 << 64) / m) {}
    int reduce(u64 a){
        u64 q = ((u128)a * b) >> 64;
        int r = a - q * m;
        return r < m ? r : r - m;
    }
} z(2);

int main(){
    cin >> n >> mod;
    z = fastmod(mod);
    cout << z.reduce(n);
}

其他玄学卡常

  1. \(for\)循环里,++\(i\)\(i\)++大概快了一倍
  2. 经常调用的局部变量用\(register\)会快很多
  3. 函数前加\(inline\),可以减少函数调用时间(递归加\(inline\)有出事风险)
  4. 函数传参加引用和\(const\),也会快一些
  5. 三目运算符比\(if\)快(就是不太可读
  6. 常量表达式前加\(constexpr\),可以在编译过程中就得到计算结果
  7. \(vector\)中,\(emplace\_back\)\(push\_back\)省去了拷贝或移动元素的过程(可能快一些)
  8. 循环比递归快(但是递归好写啊
  9. 据说逗号比分号快(可能是迷信,优化不大)
  10. 位运算比普通运算快(虽然快不了多少,但是有时候写得比较方便
  11. 引用比返回值快(可能是真的,优化不大)
    to be continue~

edit

posted @ 2022-11-16 16:03  雨夜风月  阅读(48)  评论(0编辑  收藏  举报