P3810 【模板】三维偏序(陌上花开)
CDQ分治:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int rd() {
int x = 0, w = 1;
char ch = 0;
while (ch < '0' || ch > '9') {
if (ch == '-') w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + (ch - '0');
ch = getchar();
}
return x * w;
}
void wt(int x) {
static int sta[35];
int f = 1;
if(x < 0) f = -1,x *= f;
int top = 0;
do {
sta[top++] = x % 10, x /= 10;
} while (x);
if(f == -1) putchar('-');
while (top) putchar(sta[--top] + 48);
}
const int N = 2e5+5;
struct query{
int x,y,z,w,ans;
};
bool cmpx(query a,query b) {
if(a.x == b.x) {
if(a.y == b.y)
return a.z < b.z;
return a.y < b.y;
}
return a.x < b.x;
}
bool cmpy(query a,query b) {
if(a.y == b.y)
return a.z < b.z;
return a.y < b.y;
}
#define lowbit(x) ((x) & (-x))
int n,k,c[N];
query a[N],b[N];
int t[N];
void add(int x,int k) {while(x < N) t[x] += k,x += lowbit(x);}
int ask(int x){int res = 0;while(x > 0) res += t[x],x -= lowbit(x);return res;}
void cdq(int l,int r) {
if(l == r) return;
int mid = (l + r) >> 1;
cdq(l,mid),cdq(mid + 1,r);
sort(a + l,a + mid + 1,cmpy);
sort(a + mid + 1,a + r + 1,cmpy);
int pl = l,pr;
for(int pr = mid + 1;pr <= r;pr++) {
while(a[pr].y >= a[pl].y && pl <= mid)
add(a[pl].z,a[pl].w),pl++;
a[pr].ans += ask(a[pr].z);
}
for(int i = l;i<pl;i++)
add(a[i].z,-a[i].w);
}
signed main() {
n = rd(),k = rd();
for(int i = 1;i<=n;i++)
b[i].x = rd(),b[i].y = rd(),b[i].z = rd();
sort(b + 1,b + n + 1,cmpx);
int C = 0,top = 0;
for(int i = 1;i <= n;i++) {
C++;
if(b[i].x != b[i + 1].x || b[i].y != b[i + 1].y || b[i].z != b[i + 1].z)
a[++top] = b[i],a[top].w = C,C = 0;
}
cdq(1,top);
for(int i = 1;i<=top;i++)
c[a[i].ans + a[i].w - 1] += a[i].w;
for(int i = 0;i<n;i++)
wt(c[i]),putchar('\n');
return 0;
}
实用普通模板
借学长
c
k
a
i
n
ckain
ckain 的 实用模板
我为什么不写一个呢?因为我太懒了
Fast Read & Fast Write
int rd() {
int x = 0, w = 1;
char ch = 0;
while (ch < '0' || ch > '9') {
if (ch == '-') w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + (ch - '0');
ch = getchar();
}
return x * w;
}
void wt(int x) {
static int sta[35];
int f = 1;
if(x < 0) f = -1,x *= f;
int top = 0;
do {
sta[top++] = x % 10, x /= 10;
} while (x);
if(f == -1) putchar('-');
while (top) putchar(sta[--top] + 48);
}
Mod_int
template<int Mo> struct mint {
int x;
mint(int _x=0) {x=(_x+Mo)%Mo;}
friend void print(mint a, char ch=0) {printf("%d", a.x); if(ch) putchar(ch);}
friend mint qpow(mint a, int b) {
mint re(1); for(; b; b>>=1, a=a*a) if(b&1) re=re*a; return re;
}
friend mint qpow(int a,int b) {
mint re(1);for(; b; b >>= 1,a = (a * a) % Mo) if(b & 1) re = re * a;return re;
}
bool operator == (mint a) {return x==a.x;}
bool operator != (mint a) {return x!=a.x;}
bool operator == (int a) {return x==a;}
bool operator != (int a) {return x!=a;}
bool operator > (mint a) {return x>a.x;}
bool operator < (mint a) {return x<a.x;}
bool operator >= (mint a) {return x>=a.x;}
bool operator <= (mint a) {return x<=a.x;}
bool operator > (int a) {return x>a;}
bool operator < (int a) {return x<a;}
bool operator >= (int a) {return x>=a;}
bool operator <= (int a) {return x<=a;}
mint operator - () {return *this * (Mo-1);}
friend mint operator + (mint a, mint b) {a.x+=b.x; if(a.x>=Mo) a.x-=Mo; return a;}
friend mint operator - (mint a, mint b) {a.x-=b.x; if(a.x<0) a.x+=Mo; return a;}
friend mint operator * (mint a, mint b) {return mint(1ll*a.x*b.x%Mo);}
friend mint operator / (mint a, mint b) {return a*qpow(b, Mo-2);}
friend mint operator + (mint a, int b) {a.x+=b; a.x = (a.x + b) % Mo; return a;}
friend mint operator - (mint a, int b) {a.x-=b; a.x = (a.x - b + Mo) % Mo; return a;}
friend mint operator * (mint a, int b) {return mint(1ll*a.x*b%Mo);}
friend mint operator / (mint a, int b) {return a*qpow(mint(b), Mo-2);}
mint operator += (mint a) {return *this=*this+a;}
mint operator -= (mint a) {return *this=*this-a;}
mint operator *= (mint a) {return *this=*this*a;}
mint operator /= (mint a) {return *this=*this/a;}
mint operator += (int a) {return *this=*this+a;}
mint operator -= (int a) {return *this=*this-a;}
mint operator *= (int a) {return *this=*this*a;}
mint operator /= (int a) {return *this=*this/a;}
};
自定义复数
struct C {
double r,i;
C() {r = 0,i = 0;}
C(double a,double b) {r = a,i = b;}
friend C operator + (const C &a,const C &b) {return C(a.r + b.r,a.i - b.i);}
friend C operator - (const C &a,const C &b) {return C(a.r - b.r,a.i - b.i);}
friend C operator * (const C &a,const C &b) {
return C(a.r * b.r - a.i * b.i,a.r * b.i + a.i * b.r);
}
void operator += (const C &b) {r += b.r;i += b.i;}
void operator *= (const C &b) {double t = r;r = r * b.r - i * b.i;i = t * b.i + i * b.r;}
};
LinkFrontStar
const int N = 1e6;
struct edge{
int head[N],nxt[N<<1],to[N<<1],val[N<<1],cnt;
edge(){memset(head,-1,sizeof(head));}
void addWithVal(int u,int v,int w) {
nxt[cnt] = head[u];
to[cnt] = v;
val[cnt] = w;
head[u] = cnt++;
}
void addWithoutVal(int u,int v) {
nxt[cnt] = head[u];
to[cnt] = v;
head[u] = cnt++;
}
};
自动拆矩阵
const int K=10, P=998244353;
//!矩阵阶数
int m=8;
struct Mat{
int c[K][K];
Mat(bool bas=false){
mset(c, 0);
if(bas) for(int i=0; i<m; i++) c[i][i]=1;
}
int &operator ()(int i, int j){return c[i][j];}
int operator ()(int i, int j)const{return c[i][j];}
//debug
Mat print(){
for(int i=0; i<m; i++){
for(int j=0; j<m; j++){
debug("%d ", c[i][j]);
}
debug("\n");
}
}
//
Mat operator *(const Mat &o)const{
Mat re;
for(int i=0; i<m; i++){
for(int j=0; j<m; j++){
for(int k=0; k<m; k++){
(re(i, j)+=(ll)c[i][k]*o(k, j)%P)%=P;
}
}
}
return re;
}
};
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
template<typename T> T rnr(T l, T r){return l+rng()%(r-l+1);}
vector<Mat> choice;
//!输入矩阵列表
void give_choice(){
}
Mat get_rand_mat(){
return choice[rnr(0, (int)choice.size()-1)];
}
int state[K][K];
void identify(){
Mat o=get_rand_mat();
for(int i=0; i<m; i++){
for(int j=0; j<m; j++){
state[i][j]=o(i, j);
}
}
int T=20, TT=500;
for(int _=1; _<=T; _++){
o=Mat(true);
for(int __=1; __<=TT; __++, o=o*get_rand_mat()){
for(int i=0; i<m; i++){
for(int j=0; j<m; j++) if(state[i][j]!=-1){
if(state[i][j]!=o(i, j)) state[i][j]=-1;
}
}
}
}
}
void print(){
//矩阵拆解的结果
printf("\nchanged position:\n");
for(int i=0; i<m; i++){
for(int j=0; j<m; j++){
if(state[i][j]==-1) printf("m%d%d, ", i, j);
}
}
puts("");
//输入矩阵拆解后的表达
printf("\nmatrix choice:\n");
for(int i=0; i<(int)choice.size(); i++){
printf("Mat %d:\n", i);
for(int j=0; j<m; j++){
for(int k=0; k<m; k++) if(state[j][k]==-1){
printf("m%d%d=%d, ", j, k, choice[i](j, k));
}
}
puts("");
}
//单位矩阵拆解后的表达
printf("Bas:\n");
for(int j=0; j<m; j++){
for(int k=0; k<m; k++) if(state[j][k]==-1){
printf("m%d%d=%d, ", j, k, j==k);
}
}
puts("");
//矩阵乘法
printf("\nmatrix and matrix:\n");
for(int i=0; i<m; i++){
for(int j=0; j<m; j++) if(state[i][j]==-1){
printf("re.m%d%d=", i, j);
bool first=true;
for(int k=0; k<m; k++){
if(!state[i][k] || !state[k][j]) continue;
if(!first) printf("+");
first=false;
if(state[i][k]==-1 || state[k][j]==-1){
state[i][k]==-1 ? printf("m%d%d", i, k) : printf("%d", state[i][k]);
printf("*");
state[k][j]==-1 ? printf("o.m%d%d", k, j) : printf("%d", state[k][j]);
}
else printf("%d", state[i][k]*state[k][j]);
}
printf(",\n");
}
}
//向量乘矩阵
printf("\nvector and matrix:\n");
for(int i=0; i<m; i++){
printf("re.v%d=", i);
bool first=true, exist=false;
for(int j=0; j<m; j++){
if(!state[j][i]) continue;
exist=true;
if(!first) printf("+");
first=false;
printf("v%d*", j);
state[j][i]==-1 ? printf("o.m%d%d", j, i) : printf("%d", state[j][i]);
}
if(!exist) printf("0");
printf(",\n");
}
}
Hash_With_Two_Mod
不得不说 operator []
很好用
尤其是用在矩阵上
比如写动态DP时
可以省去很多反直觉的 a.m[][]
直接使用 a[][]
struct Hash{
const int mod_1 = 1e9+7,mod_2 = 1e9+9;
int x,y;
Hash(){}
Hash(int _x,int _y) {x = _x,y = _y;}
int operator [](const int pos) {return pos ? y : x;}
friend Hash operator +(Hash a,Hash b) {
return Hash((a[0] + b[0]) % a.mod_1,(a[1] + b[1]) % a.mod_2);
}
friend Hash operator -(Hash a,Hash b) {
return Hash((a[0] - b[0] + a.mod_1) % a.mod_1,(a[1] - b[1] + a.mod_2) % a.mod_2);
}
friend Hash operator *(Hash a,Hash b) {
return Hash((a[0] * b[0]) % a.mod_1,(a[1] * b[1]) % b.mod_2);
}
void operator = (Hash a) {x = a.x,y = a.y;}
}base(131,13331);
超级快读
struct FastIO
{
#define get( ) getchar( )
#define put(x) putchar(x)
public:
inline FastIO &operator >>(char &t) {
t = get(); return *this;
}
inline FastIO &operator >>(char *t) {
while((*t = get()) != '\n') *(++t) = '\0';
return *this;
}
template <typename type>
inline FastIO &operator >>(type &x) {
x = 0; register int sig = 1; register char ch = get();
while (ch < 48 || ch > 57) { if (ch == '-') sig = -1; ch = get(); }
while (ch > 47 && ch < 58) x = (x << 3) + (x << 1) + (ch ^ 48),
ch = get(); x *= sig;
return *this;
}
template <typename type>
inline FastIO &operator <<(type x) {
if (!x) put('0'); if (x < 0) put('-'), x = -x; static char vec[50];
register int len = 0; while (x) vec[len++] = x % 10 + '0', x /= 10;
while (len--) put(vec[len]);
return *this;
}
template <typename type>
inline FastIO &operator <<(type *t) {
for (; *t; t++) put(*t);
return *this;
}
inline FastIO &operator <<(char t) {
put(t);
return *this;
}
}IO;
【模板】“动态 DP”&动态树分治
题面:
题目描述
给定一棵 n n n 个点的树,点带点权。
有 m m m 次操作,每次操作给定 x , y x,y x,y,表示修改点 x x x 的权值为 y y y。
你需要在每次操作之后求出这棵树的最大权独立集的权值大小。
输入格式
第一行有两个整数,分别表示结点个数 n n n 和操作个数 m m m。
第二行有 n n n 个整数,第 i i i 个整数表示节点 i i i 的权值 a i a_i ai。
接下来 ( n − 1 ) (n - 1) (n−1) 行,每行两个整数 u , v u, v u,v,表示存在一条连接 u u u 与 v v v 的边。
接下来 m m m 行,每行两个整数 x , y x,y x,y,表示一次操作,修改点 x x x 的权值为 y y y。
输出格式
对于每次操作,输出一行一个整数表示答案。
样例 #1
样例输入 #1
10 10 -11 80 -99 -76 56 38 92 -51 -34 47 2 1 3 1 4 3 5 2 6 2 7 1 8 2 9 4 10 7 9 -44 2 -17 2 98 7 -58 8 48 3 99 8 -61 9 76 9 14 10 93
样例输出 #1
186 186 190 145 189 288 244 320 258 304
提示
数据规模与约定
- 对于 30 % 30\% 30% 的数据,保证 n , m ≤ 10 n,m\le 10 n,m≤10。
- 对于 60 % 60\% 60% 的数据,保证 n , m ≤ 1 0 3 n,m\le 10^3 n,m≤103。
- 对于 100 % 100\% 100% 的数据,保证 1 ≤ n , m ≤ 1 0 5 1\le n,m\le 10^5 1≤n,m≤105, 1 ≤ u , v , x ≤ n 1 \leq u, v , x \leq n 1≤u,v,x≤n, − 1 0 2 ≤ a i , y ≤ 1 0 2 -10^2 \leq a_i, y \leq 10^2 −102≤ai,y≤102。
dp 套 dp
首先,因为最大独立集的dp为
{ f i , 0 = ∑ j ∈ s o n i max ( f j , 0 , f j , 1 ) ; f i , 1 = ∑ j ∈ s o n i f j , 0 ; \begin{align*} \begin{cases} f_{i,0} = \sum_{j \in son_i} \max(f_{j,0},f_{j,1}); \\ f_{i,1} = \sum_{j \in son_i} f_{j,0}; \end{cases} \end{align*} {fi,0=∑j∈sonimax(fj,0,fj,1);fi,1=∑j∈sonifj,0;
这个 Σ \Sigma Σ 太烦了,我们考虑优化状态
我们将 i i i 的孩子分为重儿子和轻儿子
因为有了重链剖分,就有了轻儿子和重儿子之分
我们设 g i , 0 g_{i,0} gi,0 为 i i i 的轻儿子中可选可不选的最大值, G i , 1 G_{i,1} Gi,1 为 i i i 的轻儿子都不选的最大值
那么最大独立集的dp为
(ps:以下的 j j j 是 i i i 的重儿子)
{ f i , 0 = g i , 0 + max ( f j , 0 , f j , 1 ) f i , 1 = g i , 1 + a i + f j , 0 ; \begin{align*} \begin{cases} f_{i,0} = g_{i,0} + \max(f_{j,0},f_{j,1}) \\ f_{i,1} = g_{i,1} + a_i + f_{j,0}; \end{cases} \end{align*} {fi,0=gi,0+max(fj,0,fj,1)fi,1=gi,1+ai+fj,0;
我们发现这个 g i , 1 + a i g_{i,1} + a_i gi,1+ai 很难看,两个式子要尽量类似
所以我们将 a i a_i ai 划分到 g i , 1 g_{i,1} gi,1 中,即将 g i , 1 g_{i,1} gi,1 的定义改为,选该点且轻儿子都不选的最大值
那么最大独立集的dp为
{
f
i
,
0
=
g
i
,
0
+
max
(
f
j
,
0
,
f
j
,
1
)
f
i
,
1
=
g
i
,
1
+
f
j
,
0
;
\begin{align*} \begin{cases} f_{i,0} = g_{i,0} + \max(f_{j,0},f_{j,1}) \\ f_{i,1} = g_{i,1} + f_{j,0}; \end{cases} \end{align*}
{fi,0=gi,0+max(fj,0,fj,1)fi,1=gi,1+fj,0;
接下来如何做呢?
我们不难发现 max \operatorname{max} max 是有结合律的,而矩阵乘法也有
那么,我们再变形
{ f i , 0 = max ( g i , 0 + f j , 0 , g i , 0 + f j , 1 ) f i , 1 = max ( g i , 1 + f j , 0 , − ∞ ) ; \begin{align*} \begin{cases} f_{i,0} = \max(g_{i,0} + f_{j,0},g_{i,0} + f_{j,1}) \\ f_{i,1} = \max(g_{i,1} + f_{j,0},-\infty); \end{cases} \end{align*} {fi,0=max(gi,0+fj,0,gi,0+fj,1)fi,1=max(gi,1+fj,0,−∞);
那么,我们定义广义矩阵乘法,在链上push_up
广义矩阵乘法:
struct matrix{
int m[2][2];
matrix(){memset(m,-0x3f,sizeof(m));}
matrix(bool flag) {m[0][0] = m[1][1] = 1;}
int* operator [](const int pos) {return m[pos];}
friend matrix operator * (matrix a,matrix b) {
matrix c;
for(int k = 0;k<2;k++)
for(int i = 0;i<2;i++)
for(int j = 0;j<2;j++)
c[i][j] = max(c[i][j],a[i][k] + b[k][j]);
return c;
}
}w[N];
如何设计转移矩阵呢?
$$
\begin{bmatrix}
f_{i,0} \
f_{i,1} \
\end{bmatrix}
\mathrm{U} \times
\begin{bmatrix}
f_{j,0} \
f_{j,1} \
\end{bmatrix}
$$
求出 U \mathrm{U} U 就好了
不难计算,
U
=
[
g
i
,
0
g
i
,
0
g
i
,
1
−
∞
]
\mathrm{U} = \begin{bmatrix} g_{i,0} & g_{i,0} \\ g_{i,1} & -\infty \end{bmatrix}
U=[gi,0gi,1gi,0−∞]
然后是修改链的细节
我们要查询的是每条链汇聚到 root \operatorname{root} root 上节点的总 ∗ \color{red}{*} ∗ 积
因为本题初始化 f i , 0 = 0 , f i , 1 = a i f_{i,0} = 0,f_{i,1} = a_i fi,0=0,fi,1=ai,所以直接查询答案矩阵的 g i , 0 g_{i,0} gi,0 和 g i , 1 g_{i,1} gi,1 就可以了
在修改的时候,我们采取对原矩阵组进行修改,然后让线段树上的对于点直接读取原矩阵组
修改一个点,只会影响到这个链的链头的父亲(因为链头的父亲的矩阵就是由每一条链做 ∗ \color{red}{*} ∗ 积来的)
所以我们在修改完后,对链头的父亲进行一次更新(更新的值要查询修改前后整条链的矩阵 ∗ \color{red}{*} ∗ 积 )
还有全局平衡二叉树的做法
我是蒟蒻,表示看不懂
请读者自行研究
树剖AC
AC-code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int rd() {
int x = 0, w = 1;
char ch = 0;
while (ch < '0' || ch > '9') {
if (ch == '-') w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + (ch - '0');
ch = getchar();
}
return x * w;
}
void wt(int x) {
static int sta[35];
int f = 1;
if(x < 0) f = -1,x *= f;
int top = 0;
do {
sta[top++] = x % 10, x /= 10;
} while (x);
if(f == -1) putchar('-');
while (top) putchar(sta[--top] + 48);
}
const int N = 1e5+5;
struct matrix{
int m[2][2];
matrix(){memset(m,-0x3f,sizeof(m));}
matrix(bool flag) {m[0][0] = m[1][1] = 1;}
int* operator [](const int pos) {return m[pos];}
friend matrix operator * (matrix a,matrix b) {
matrix c;
for(int k = 0;k<2;k++)
for(int i = 0;i<2;i++)
for(int j = 0;j<2;j++)
c[i][j] = max(c[i][j],a[i][k] + b[k][j]);
return c;
}
}w[N];
int n,m,a[N],head[N],nxt[N<<1],to[N<<1],cnt;
void init() {memset(head,-1,sizeof(head));cnt = 0;}
void add(int u,int v) {
nxt[cnt] = head[u];
to[cnt] = v;
head[u] = cnt++;
}
int F[N][2];
int fa[N],top[N],son[N],siz[N],dep[N],id[N],low[N],_id[N];
void dfs1(int x,int f) {
fa[x] = f;
siz[x] = 1;
dep[x] = dep[f] + 1;
for(int i = head[x];~i;i = nxt[i]) {
int y = to[i];
if(y ^ f) {
dfs1(y,x);
siz[x] += siz[y];
if(siz[son[x]] < siz[y]) son[x] = y;
}
}
}
int num;
void dfs2(int x,int topx) {
id[x] = ++num;
_id[num] = x;
top[x] = topx;
low[topx] = max(id[x],low[topx]);
F[x][0] = 0,F[x][1] = a[x];
w[x][0][0] = w[x][0][1] = 0;
w[x][1][0] = a[x];
if(!son[x]) return;
dfs2(son[x],topx);
F[x][0] += max(F[son[x]][0],F[son[x]][1]);
F[x][1] += F[son[x]][0];
for(int i = head[x];~i;i = nxt[i]) {
int y = to[i];
if(y ^ fa[x] && y ^ son[x]){
dfs2(y,y);
F[x][0] += max(F[y][0],F[y][1]);
F[x][1] += F[y][0];
w[x][0][0] += max(F[y][0],F[y][1]);
w[x][0][1] = w[x][0][0];
w[x][1][0] += F[y][0];
}
}
}
namespace sgt{
#define ls (p << 1)
#define rs (p << 1 | 1)
#define mid ((pl + pr) >> 1)
matrix t[N<<2];
void push_up(int p) {
t[p] = t[ls] * t[rs];
}
void build(int p,int pl,int pr) {
if(pl == pr) {
t[p] = w[_id[pl]];
return;
}
build(ls,pl,mid);
build(rs,mid+1,pr);
push_up(p);
}
void update(int p,int pl,int pr,int k) {
if(pl == pr) {
t[p] = w[_id[pl]];
return;
}
if(k <= mid) update(ls,pl,mid,k);
else update(rs,mid+1,pr,k);
push_up(p);
}
matrix query(int p,int pl,int pr,int l,int r) {
if(l <= pl && pr <= r) return t[p];
if(r <= mid) return query(ls,pl,mid,l,r);
else if(l > mid) return query(rs,mid+1,pr,l,r);
else return query(ls,pl,mid,l,r) * query(rs,mid+1,pr,l,r);
}
}
void update(int u,int v) {
w[u][1][0] += v - a[u];
a[u] = v;
matrix p,q;
while(u) {
p = sgt::query(1,1,n,id[top[u]],low[top[u]]);
sgt::update(1,1,n,id[u]);
q = sgt::query(1,1,n,id[top[u]],low[top[u]]);
u = fa[top[u]];
w[u][0][0] += max(q[0][0],q[1][0]) - max(p[0][0],p[1][0]);
w[u][0][1] = w[u][0][0];
w[u][1][0] += q[0][0] - p[0][0];
}
}
signed main() {
init();
n = rd();m = rd();
for(int i = 1;i<=n;i++)
a[i] = rd();
for(int i = 1;i<n;i++){
int u = rd(),v = rd();
add(u,v);add(v,u);
}
dfs1(1,0);dfs2(1,1);
sgt::build(1,1,n);
while(m--) {
int x = rd(),y = rd();
update(x,y);
matrix ans = sgt::query(1,1,n,id[1],low[1]);
wt(max(ans[0][0],ans[1][0]));
putchar('\n');
}
return 0;
}
高斯消元
#include<bits/stdc++.h>
using namespace std;
const int N = 105;
const double Exp = 1e-12;
int n;
double a[N][N];
signed main() {
scanf("%d",&n);
for(int i = 1;i<=n;i++)
for(int j = 1;j<=n + 1;j++)
scanf("%lf",&a[i][j]);
for(int i = 1;i<=n;i++){
int mx = i;
for(int j = i + 1;j<=n;j++)
if(fabs(a[j][i]) > fabs(a[mx][i]))
mx = j;
if(mx != i)
for(int j = 1;j<=n + 1;j++)
swap(a[mx][j],a[i][j]);
if(fabs(a[i][i]) < Exp) {
puts("-1");
return 0;
}
for(int j = 1;j<=n;j++) {
if(j ^ i) {
double p = a[j][i] / a[i][i];
for(int k = 1;k<=n + 1;k++)
a[j][k] -= a[i][k] * p;
}
}
}
for(int i = 1;i<=n;i++)
printf("x%d=%.2lf\n",i,(fabs(a[i][n + 1] / a[i][i]) < Exp) ? 0:a[i][n + 1] / a[i][i]);
return 0;
}
BSGS
#include<bits/stdc++.h>
using namespace std;
#define int long long
int rd() {
int x = 0, w = 1;
char ch = 0;
while (ch < '0' || ch > '9') {
if (ch == '-') w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + (ch - '0');
ch = getchar();
}
return x * w;
}
void wt(int x) {
static int sta[35];
int f = 1;
if(x < 0) f = -1,x *= f;
int top = 0;
do {
sta[top++] = x % 10, x /= 10;
} while (x);
if(f == -1) putchar('-');
while (top) putchar(sta[--top] + 48);
}
int p,b,n,base;
map<int,int> m;
int qpow(int x,int k) {
int res = 1;
while(k) {
if(k & 1) res = (res * x) % p;
x = (x * x) % p;
k >>= 1;
}
return res;
}
bool bsgs(){
int cur = 1;
for(int i = 0;i<base;i++,cur = cur * b % p) {
if(!m.count(cur)) m[cur] = i;
if(cur == n) {
printf("%lld",i);
return true;
}
}
for(int i = 1,now = 1;i <= base;i++) {
now = now * cur % p;
if(!now) continue;
int key = qpow(now,p - 2) * n % p;
if(m.count(key)) {
printf("%lld",i * base + m[key]);
return true;
}
}
return false;
}
signed main() {
p = rd(),b = rd(),n = rd();
base = sqrt(p);
if(!bsgs()) puts("no solution");
return 0;
}
树Hash
#include<bits/stdc++.h>
using namespace std;
int rd() {
int x = 0, w = 1;
char ch = 0;
while (ch < '0' || ch > '9') {
if (ch == '-') w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + (ch - '0');
ch = getchar();
}
return x * w;
}
void wt(int x) {
static int sta[35];
int f = 1;
if(x < 0) f = -1,x *= f;
int top = 0;
do {
sta[top++] = x % 10, x /= 10;
} while (x);
if(f == -1) putchar('-');
while (top) putchar(sta[--top] + 48);
}
#define ull unsigned long long
const int N = 1e6+10;
const ull mask = chrono::steady_clock::now().time_since_epoch().count();
ull shift(ull x) {
x ^= mask;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
x ^= mask;
return x;
}
ull Hash[N];
vector<int> edge[N];
set<ull> trees;
int n;
void getHash(int x,int fa) {
Hash[x] = 1;
for(int i : edge[x]) {
if(i == fa) continue;
getHash(i,x);
Hash[x] += shift(Hash[i]);
}
trees.emplace(Hash[x]);
}
signed main() {
n = rd();
for(int i = 1;i<n;i++) {
int u = rd(),v = rd();
edge[u].emplace_back(v);
edge[v].emplace_back(u);
}
getHash(1,0);
wt(trees.size());
return 0;
}
异或基
#include<bits/stdc++.h>
using namespace std;
#define int long long
int rd() {
int x = 0, w = 1;
char ch = 0;
while (ch < '0' || ch > '9') {
if (ch == '-') w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + (ch - '0');
ch = getchar();
}
return x * w;
}
void wt(int x) {
static int sta[35];
int f = 1;
if(x < 0) f = -1,x *= f;
int top = 0;
do {
sta[top++] = x % 10, x /= 10;
} while (x);
if(f == -1) putchar('-');
while (top) putchar(sta[--top] + 48);
}
const int N = 55;
int n,k,a[N],ans;
void gauss() {
for(int i = 62;i>=0;i--) {
for(int j = k;j<n;j++)
if((a[j] >> i) & 1) {swap(a[k],a[j]);break;}
if((a[k] >> i & 1) == 0) continue;
for(int j = 0;j<n;j++)
if((a[j] >> i & 1) && j != k)
a[j] ^= a[k];
k++;
if(k == n) break;
}
}
signed main() {
n = rd();
for(int i = 0;i<n;i++) a[i] = rd();
gauss();
for(int i = 0;i<k;i++) ans ^= a[i];
wt(ans);
return 0;
}
迪杰斯特拉
struct node{
int x,d;
node(int x,int d) : x(x),d(d){}
friend bool operator < (node a,node b) {
return a.d > b.d;
}
};
int dis[N];
bool vis[N];
void dij() {
memset(vis,0,sizeof(vis));
memset(dis,0x3f,sizeof(dis));
priority_queue<node> q;
q.emplace(node(1,0));
dis[1] = 0;
while(q.size()) {
node t = q.top();
q.pop();
if(vis[t.x]) continue;
vis[t.x] = true;
for(int i = g.head[t.x];~i;i = g.nxt[i]) {
int y = g.to[i];
if(dis[y] > dis[t.x] + g.val[i]) {
dis[y] = dis[t.x] + g.val[i];
q.emplace(node(y,dis[y]));
}
}
}
}
EXGCD
void exgcd(int a,int b,int &x,int &y){
if(b==0){
x=1,y=0;
return;
}
exgcd(b,a%b,y,x);
y-=(a/b)*x;
}
CRT(China Remain Theory)
LL CRT(int k, LL *a, LL *r) {
LL n = 1, ans = 0;
for (int i = 1; i <= k; i++)
n = n * r[i];
for (int i = 1; i <= k; i++) {
LL m = n / r[i], b, y;
exgcd(m, r[i], b, y); // b * m mod r[i] = 1
ans = (ans + a[i] * m * b % n) % n;
}
return (ans % n + n) % n;
}
FFT
#include<bits/stdc++.h>
using namespace std;
const int N = 4.2e6;
const double pi = acos(-1);
int n,r[N];
struct C {
double r,i;
C() {r = 0,i = 0;}
C(double a,double b) {r = a,i = b;}
friend C operator + (const C &a,const C &b) {return C(a.r + b.r,a.i - b.i);}
friend C operator - (const C &a,const C &b) {return C(a.r - b.r,a.i - b.i);}
friend C operator * (const C &a,const C &b) {
return C(a.r * b.r - a.i * b.i,a.r * b.i + a.i * b.r);
}
void operator += (const C &b) {r += b.r;i += b.i;}
void operator *= (const C &b) {double t = r;r = r * b.r - i * b.i;i = t * b.i + i * b.r;}
}f[N],g[N];
void FFT(C *a,const int op) {
C W,w,t,*a0,*a1;
int i,j,k;
for(int i = 0;i<n;i++)
if(i < r[i])
swap(a[i],a[r[i]]);
for(int i = 1;i<n;i <<= 1)
for(W = C(cos(pi / i),sin(pi / i) * op),j = 0;j < n;j += i << 1)
for(w = C(1,0),a1 = i + (a0 = a + j),k = 0;k < i; ++k,++a0,++a1,w *= W)
t = *a1*w,*a1 = *a0 - t,*a0 += t;
}
int m,l = 0;
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
cin>>n>>m;
for(int i = 0;i<=n;i++) cin>>f[i].r;
for(int i = 0;i<=m;i++) cin>>g[i].r;
for(m += n,n = 1;n <= m;n <<= 1,++l);
for(int i = 0;i<n;i++) r[i] = (r[i >> 1] >> 1 | ((i & 1)<<(l - 1))); // rader 映射
FFT(f,1);FFT(g,1); // DFT
for(int i = 0;i<n;i++) f[i] *= g[i]; // 整合成 f * g 函数的FFT
FFT(f,-1);// 做一遍IDFT还原
for(int i = 0;i<=m;i++) printf("%.0lf ",fabs(f[i].r)/n);
return 0;
}