_rqy's Code Style for OI


_rqy's Code Style for OI

Inspired by Menci's Code Style for OI

本文介紹_rqy的OI中的代碼規范。其來源主要為_rqy的長期積累及參考Google代碼規范、Menci的規范。

可能會update。

概述

#include語句必須置於整個程序的開頭。

不應using namespace foo;。若有必要可以using foo::bar;

單行字符數必須不超過80。

預編譯

#include的多個庫順序可有以下兩種:

  1. C++標准庫在前,之后是C標准庫,再后為其它(如交互庫等)。(工程代碼中,本cpp所對應的.h文件應置於開頭。)
  2. (僅適用於OI)按字典序依次排列。

可以使用#include <foo>絕不使用#include "foo"

如果有多層嵌套#if #endif,#endif后應有對應的注釋標識出與其對應的#if

盡量不要適用#define而使用const, typedef, inline

所有預編譯命令不應縮進(見下)。

縮進

每個代碼塊采用2空格縮進。

空格及換行

大括號換行。

需要加空格的地方:

  1. 二元運算符(包括賦值運算符)兩側(,運算符例外,見下);
  2. ,;的右邊(如果其不處於行尾);
  3. if, for等控制流關鍵字與其后的左括號之間 ;
  4. do-while中的whileif-else中的else與其前面的右大括號之間;
  5. 所有左大括號的左側(根據不換行的策略,左大括號不應處於行首);
  6. ? :的兩側(包括構造函數初始化列表中的:);
  7. 類型中*,&的左側(如:const int &a, int A(int *&a)。);
  8. 花括號與其內部語句/數組初始化列表之間(如果在同一行);
  9. 常成員函數的const兩側。

一定不能加空格的地方:

  1. 小括號及中括號與其內部的表達式/參數列表之間;
  2. 函數名與左括號之間(包括聲明/定義/使用);
  3. 單目運算符(!,-,*,&,~)之后(或自增自減運算符與其操作數之間);
  4. ,;的左側;
  5. 類型中*,&的右側;
  6. .,->,::的兩側;
  7. operator與所要重載的運算符之間(運算符與參數列表之間,根據第2條,也不應空格)。

若表達式過長內部可以換行,運算符處於行首(而非行尾);縮進以使表達式對齊為准;換行的優先級較高的子表達式也應加括號以避免誤讀。

參數列表/初始化列表過長時內部也可換行,逗號處於行尾;縮四空格。

例子:

struct AVeryVeryVeryVeryVeryVeryVeryVeryVeryLongStruct{
  int aVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongVariable, d;
  AVeryVeryVeryVeryVeryVeryVeryVeryVeryLongStruct(int a, int b, int c, int d)
      : aVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongVariable(a) {
    this->d = b + c * d;
  }
};

int main() {
  int thisVariableIsToBeLong = 2, thisVariableIsToBeLongerAndLonger = 23;
  AVeryVeryVeryVeryVeryVeryVeryVeryVeryLongStruct s(
      thisVariableIsToBeLong, thisVariableIsToBeLong,
      thisVariableIsToBeLongerAndLonger,
      thisVariableIsToBeLongerAndLonger
  );
  printf("%d\n", s.d);
}

空行

所有#include <foobar>using foo::bar;之間不應空行,之后應空一行。

一系列常量定義的上下應有空行。

函數/結構體定義兩側應有空行(一系列聯系密切的模板函數,如min,max,之間可以不空行)。

一系列全局變量定義的上下應有空行。

語句之間可根據其意義酌情空行。

任何位置不能出現連續的兩個(或以上)空行。

函數定義

main函數返回值必須為int,return 0不可忽略;

類/結構體傳參在大多數情況下不應傳值(除非難以避免地產生拷貝,或一些特殊要求),而應傳引用。

極其簡短的函數可以寫作一行(但絕不能超過80字符),此時花括號內部應有空格(空函數體{}除外)。

單個函數的長度不應過長(例如超過100行)。

命名規則

一般情況下應采用駝峰命名法,變量開頭小寫,函數/類/結構體開頭大寫。

特例:

  1. main函數;
  2. 變量可以以一個小寫字母命名;
  3. 全局數組名可使用1個大寫字母+0~2個數字命名,如A, T1,F01
  4. 模板。如readInt, min, max,pow_mod;
  5. 采用對應算法縮寫,如KMP, CRT, NTT,CDQ
  6. 常量可以大寫字母命名,如N, M
  7. 臨時變量可以以下划線開頭。

Example Code

#include <algorithm>
#include <cctype>
#include <cstdio>

typedef long long LL;

inline int readInt() {
  int ans = 0, c;
  while (!isdigit(c = getchar()));
  do ans = ans * 10 + c - '0';
  while (isdigit(c = getchar()));
  return ans;
}

const int mod = 998244353;
const int g = 3;
const int N = 200050;

inline LL pow_mod(LL x, int p) {
  LL ans = 1;
  for ((p += mod - 1) %= (mod - 1); p; p >>= 1, (x *= x) %= mod)
    if (p & 1) (ans *= x) %= mod;
  return ans;
}

LL inv[N];
int n;

void NTT(LL *A, int len, int opt) {
  for (int i = 1, j = 0; i < len; ++i) {
    int k = len;
    while (~j & k) j ^= (k >>= 1);
    if (i < j) std::swap(A[i], A[j]);
  }

  for (int h = 2; h <= len; h <<= 1) {
    LL wn = pow_mod(g, (mod - 1) / h * opt);
    for (int j = 0; j < len; j += h) {
      LL w = 1;
      for (int i = j; i < j + (h >> 1); ++i) {
        LL _tmp1 = A[i], _tmp2 = A[i + (h >> 1)] * w;
        A[i] = (_tmp1 + _tmp2) % mod;
        A[i + (h >> 1)] = (_tmp1 - _tmp2) % mod;
        (w *= wn) %= mod;
      }
    }
  }

  if (opt == -1)
    for (int i = 0; i < len; ++i)
      (A[i] *= -(mod - 1) / len) %= mod;
}

LL F[N], G[N];
LL T1[N * 4], T2[N * 4];

void Conv(LL *A, int n, LL *B, int m) {
  int len = 1;
  while (len <= n + m) len <<= 1;
  for (int i = 0; i < len; ++i)
    T1[i] = (i < n ? A[i] : 0);
  for (int i = 0; i < len; ++i)
    T2[i] = (i < m ? B[i] : 0);

  NTT(T1, len, 1);
  NTT(T2, len, 1); 
  for (int i = 0; i < len; ++i)
    (T1[i] *= T2[i]) %= mod;
  NTT(T1, len, -1);
}

void Solve(int l, int r) {
  if (l == r - 1) {
    F[l] = (l == 0 ? 1 : F[l] * inv[l] % mod);
    return;
  }

  int mid = (l + r) >> 1;
  Solve(l, mid);
  Conv(F + l, mid - l, G, r - l);
  for (int i = mid; i < r; ++i)
    (F[i] += T1[i - l]) %= mod;
  Solve(mid, r);
}

int main() {
  n = readInt();

  inv[1] = 1;
  for (int i = 2; i <= n; ++i)
    inv[i] = -(mod / i) * inv[mod % i] % mod;

  for (int i = 1; i <= n; ++i) {
    scanf("%lld", &G[i]);
    (G[i] *= i) %= mod;
  }

  Solve(0, n + 1);
  for (int i = 1; i <= n; ++i)
    printf("%lld\n", (F[i] + mod) % mod);
  return 0;
}

注:此為多項式\(\exp\)模板。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM