常见小错误 FREQUENTLY MADE MISTAKES IN OI

1. 多测忘记清空

LCA的fa数组每次也要清空

BSGS 的哈希表

2. 数据溢出或取模出错

  1. 溢出
    int相乘转long long,long long相乘转__int128
int a, b, c;
c = 1ll * a * b % M;

long long x, y, z;
z = x * y % M; // 会溢出!

// 正确写法
__int128 x, y, z;
z = x * y % m;
  1. 乘法(连乘每次都要取模),减法忘记取模
int a, b, c;
a = ((a - b) % M + M) % M; // 减法
a = 1ll * a * b % M; // 乘法
a = 1ll * a * b; // 乘法,乘1ll转long long防溢出
c = 1ll * a * b % M * c % M * ... * z % M; // 连乘

3. 使用STL或用数组模拟队列,栈等数据结构时忘记判空

4. 数位dp记忆化搜索版本,记忆化数组\(f\)是不考虑\(\text{high}\)\(\text{lead}\)的结果

也要注意初始化

ll dfs(int u, ..., bool high, bool lead)
{
	if (u < 1) {
		...
		return ...;
	}
	if (!high && !lead && f[u][cons][val] != -1) return f[u][cons][val]; // 注意是!high && !lead
	...
	if (!high && !lead) f[u][cons][val] = ret;
	return ret;
}

5. 数组开小,注意算好数组大小

6. 注意运算优先级(尤其位运算)

类别 运算符 结合顺序
后缀 () [] -> . ++ - - 从左到右
一元 + - ! ~ ++ - - (type)* & sizeof 从右到左
乘除 * / % 从左到右
加减 + - 从左到右
移位 << >> 从左到右
关系 < <= > >= 从左到右
相等 == != 从左到右
位与 AND & 从左到右
位异或 XOR ^ 从左到右
位或 OR | 从左到右
逻辑与 AND && 从左到右
逻辑或 OR || 从左到右
条件 ?: 从右到左
赋值 = += -= *= /= %= >>= <<= &= ^= |= 从右到左
逗号 , 从左到右

摘自菜鸟教程

7. 递归边界忘记return

8. 线段树的范围下标不一定是\([1, n]\),也有可能是\([0, n-1]\)(例如当线段树建在离散化后的vector上)

9. 差分时应倒序遍历数组

for (int i = n; i >= 1; i--)
	a[i] = a[i] - a[i-1];

10. 空元素的表示

对于运算而言,空元素应该理解为这个运算的单位元,即对于运算 \(\oplus\),有 \(a \oplus e = e \oplus a = a\)

例如,对于加法,空元素可用 \(0\) 表示,对于乘法,可以用 \(1\) 表示,对于矩阵乘法,可用单位矩阵 \(I\) 表示

【模板】线段树2

11. 分块时注意下标指的是块编号还是原数组下标

12. 字典树中信息是存在边上的,而不是点上

13. 倍增数组第二维是位数时,注意防止越界

建议略开大一点

int fa[N+5][24];
for (int i = 24; i >= 0; i--) // RE 注意第二维下标最多23
	fa[x][i] .....

14. 点分治

注意区分原树中传参得到的根节点,与选重心得到的新根节点

15. 题目中给出的图可能不连通

16. 局部变量记得初始化

17. 连通性相关

点双

注意特判仅有一个节点的点双
大多数题目,缩点后计算答案考虑度数为1、0的点双

点双缩点后至多有约\(2n\)个节点(原图为一条链)

18. 可持久化数据结构

每一个操作都对应一个唯一的根,且每个根都对应唯一的操作,不能多个操作对应同一个根

可持久化线段树更新时,记得从原来的版本继承数据

19. 循环中continue,记得将被跳过的必须操作处理完

20. 循环中判定无解,退出后立即判断

CF2150B

int sum = 0, ans = 1;
for (int i = mid, k = n % 2 ? 1 : 2; i > 1; i--, k += 2) {
	if (k - sum < a[i]) {
		puts("0");
		flag = 1;
		break;
	}

	ans = 1ll * ans * C(a[i], k - sum) % M;

	sum += a[i];
}

// 这一行一定要加上!不然可能上面循环中输出一个0,下面if又输出一次
if (flag) continue; // !!!

if (n - sum != a[1]) {
	puts("0");
	flag = 1;
}

if (flag) continue;

21. cdq分治

  1. 归并排序仅需一个数组,不要与整体二分混淆

  2. 归并过程中统计数据,要统计从区间\(l\)开始总计数据

正确的:(cnt统计总和)

int cnt = 0;
for (i = l, j = mid + 1; j <= r; ) {
	while (i <= mid && t2d[i].c <= t2d[j].c) {
		if (!t2d[i].tag) cnt += w[t2d[i].id];
		t3d[idx++] = t2d[i++];
	}
	if (t2d[j].tag) f[t2d[j].id] += cnt;
	t3d[idx++] = t2d[j++];
}

错误的:(应新建变量mx统计\([l, i]\)的最大值)

for (i = l, j = mid + 1; j <= r; ) {
	while (i <= mid && us[i].l <= us[j].l) {
		tmp[len++] = us[i++];
	}
	if (i > l) {
		maxl[us[j].id] = max(maxl[us[j].id], us[i - 1].l);
	}
	tmp[len++] = us[j++];
}
  1. 注意去重

  2. 注意排序规则,将能贡献给某一元素的其他元素都排在它前面(见下22)

22. 排序cmp函数

  1. 不能带等于号,严格弱序关系

  2. 如果有多个关键字,需要考虑当第一关键字相同时怎么做,是无需处理,还是应按第二关键字排序,原则是将能贡献给某一元素的其他元素都排在它前面

23. BSGS

哈希表记得多测清空

\[a^x \equiv b \pmod p \]

特判\(a=0\)\(p=1\)的情况

\[x = \begin{cases} 0, & p=1 \\ 1, & p\neq 1,\ a=0,\ b = 0 \\ 0, & p\neq 1,\ a=0,\ b = 1 \\ \text{use BSGS to calculate}, & \text{otherwise} \end{cases} \]

24. 注意不等式是否带等号

posted @ 2025-09-15 20:52  zhm0725  阅读(6)  评论(0)    收藏  举报