神说:“简洁问题触及本质。”
神说:“复杂并非深刻,混乱亦非自由。”
神说:“剥离偶然,留下必然。”
神说:“$\exp(O(n))$ 是虚伪的胜利,$\text{poly}(n)$ 是永恒的真理。”
这是一位算法竞赛前选手接收到的最后一份神谕,在他与他的朋友的精心打磨下,最终呈现出了这份礼物赠予各位。
形式化题意:
给定 $n$,将所有满足 $S\subseteq [n],1\le |S|\le 2$ 的集合 $S$ 排成一列,要求 $\{x,y\}$ 在 $\{x\}$ 与 $\{y\}$ 之间,且 $\{x\}$ 在 $\{x+1\}$ 之前。
对于每一组 $1\le i\le n,1\le j\le n(n+1)/2$ 求出 $\{i\}$ 的下标为 $j$ 的方案数。答案对给定的质数 $p$ 取模。
输入格式
共一行,两个整数 $n,p$。
输出格式
共 $n$ 行,每行 $n(n+1)/2$ 个整数。第 $i$ 行的第 $j$ 个数,表示 $\{i\}$ 的下标为 $j$ 的方案数。
样例一
input
1 851214401
output
1
样例二
input
3 922820713
output
4 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 4
样例三
input
4 682679827
output
144 0 0 0 0 0 0 0 0 0 0 0 60 60 24 0 0 0 0 0 0 0 0 0 0 24 60 60 0 0 0 0 0 0 0 0 0 0 0 144
样例四 $\sim$ 样例十
见下发文件。
数据范围
对于 $100\%$ 的数据,$1\le n\le 40,10^8< p< 10^9$。保证 $p$ 为质数。
| 子任务编号 | $n\le$ | 分值 |
|---|---|---|
| $1$ | $5$ | $5$ |
| $2$ | $10$ | $5$ |
| $3$ | $15$ | $10$ |
| $4$ | $20$ | $10$ |
| $5$ | $25$ | $15$ |
| $6$ | $30$ | $15$ |
| $7$ | $35$ | $20$ |
| $8$ | $40$ | $20$ |
我们提供 $\text{Barrett}$ 模乘算法模板以加速取模运算:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
typedef __uint128_t L;
struct FastMod {
ull b, m;
FastMod(ull b) : b(b), m(ull((L(1) << 64) / b)) {}
ull reduce(ull a) {
ull q = (ull)((L(m) * a) >> 64);
ull r = a - q * b; // can be proven that 0 <= r < 2*b
return r >= b ? r - b : r;
}
};
FastMod F(2);
int main() {
int M = 1000000007; F = FastMod(M);
ull x = 10ULL*M+3;
cout <<; x << " " << F.reduce(x) << "\n"; // 10000000073 3
}