板子们
数学
高斯消元(P2455)
#include<cstdio>
#include<cstring>
using namespace std;
int n;
double a[105][105];
void swap(double &x,double &y){double t = x; x = y; y = t;}
double abs(double x){return x > 0 ? x : -x;}
int main(){
scanf("%d",&n);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n + 1; ++j)scanf("%lf",&a[i][j]);
int op = 1, i;
for(i = 1; i <= n; ++i){
int k = op;
double mx = abs(a[op][i]);
for(int j = op + 1; j <= n; ++j)if(abs(a[j][i]) > mx){
mx = abs(a[j][i]);
k = j;
}
if(mx == 0)continue;
if(k != op)for(int j = 1; j <= n + i; ++j)swap(a[op][j], a[k][j]);
for(int j = n + 1; j >= i; --j)a[op][j] /= a[op][i];
for(int j = 1; j <= n; ++j)
if(j != op)
for(int p = n + 1; p >= i; --p)a[j][p] -= a[op][p] * a[j][i];
++op;
}
if(op > n){
for(int i = 1; i <= n; ++i){
printf("x%d=",i);
printf("%.2lf\n",a[i][n + 1]);
}
}else{
bool flag = 0;
for(int i = op; i <= n; ++i)if(a[i][n + 1]){flag = 1; break;}
if(flag)printf("-1\n");
else printf("0\n");
}
return 0;
}
多项式
fwt/fmt(and or xor)
void fwt_or(int f[], int opt){
opt = (opt + mod) % mod;
for(int l = 2, k = 1; l <= len; l <<= 1, k <<= 1)
for(int i = 0; i < len; i += l)
for(int j = 0; j < k; ++j)
f[i + j + k] = (f[i + j + k] + 1ll * opt * f[i + j] % mod) % mod;
}
void fwt_and(int f[], int opt){
opt = (opt + mod) % mod;
for(int l = 2, k = 1; l <= len; l <<= 1, k <<= 1)
for(int i = 0; i < len; i += l)
for(int j = 0; j < k; ++j)
f[i + j] = (f[i + j] + 1ll * f[i + j + k] * opt % mod) % mod;
}
void fwt_xor(int f[], int opt){
opt = opt == -1 ? inv2 : 1;
for(int l = 2, k = 1; l <= len; l <<= 1, k <<= 1)
for(int i = 0; i < len; i += l)
for(int j = 0; j < k; ++j){
int x = f[i + j], y = f[i + j + k];
f[i + j] = 1ll * opt * (x + y) % mod;
f[i + j + k] = 1ll * opt * (x - y + mod) % mod;
}
}
子集卷积
#include<map>
#include<bits/stdc++.h>
using namespace std;
int read(){
int x = 0; char c = getchar();
while(!isdigit(c))c = getchar();
do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
return x;
}
const int mod = 1e9 + 9;
const int maxn = (1 << 21) + 55;
int deg;
void add(int &x, int y){x += y; if(x >= mod)x -= mod;}
void fwt_or(int f[], int deg, int opt){
for(int l = 2, hl = 1; l <= deg; l <<= 1, hl <<= 1)
for(int i = 0; i < deg; i += l)
for(int j = i; j < i + hl; ++j)
add(f[j + hl], 1ll * f[j] * opt % mod);
}
int n, f[22][maxn], g[22][maxn], h[22][maxn], cnt[maxn];
int main(){
n = read(); deg = 1 << n;
for(int i = 1; i < deg; ++i)cnt[i] = cnt[i >> 1] + (i & 1);
for(int i = 0; i < deg; ++i)f[cnt[i]][i] = read();
for(int i = 0; i < deg; ++i)g[cnt[i]][i] = read();
for(int i = 0; i <= n; ++i)fwt_or(f[i], deg, 1), fwt_or(g[i], deg, 1);
for(int i = 0; i <= n; ++i)
for(int j = 0; j <= i; ++j)
for(int k = 0; k < deg; ++k)
add(h[i][k], 1ll * f[j][k] * g[i - j][k] % mod);
for(int i = 0; i <= n; ++i)fwt_or(h[i], deg, mod - 1);
for(int i = 0; i < deg; ++i)printf("%d ",h[cnt[i]][i]);printf("\n");
return 0;
}
fft
inline void fft(complex <double> a[], int len){
for(register int i = 1; i < len; ++i)if(i < rev[i]) swap(a[i], a[rev[i]]);
for(register int l = 2; l <= len; l <<= 1){
complex <double> wn(cos(2 * PI / l), sin(2 * PI / l));
for(register int j = 0; j < len; j += l){
complex <double> w(1, 0);
int ll = l >> 1;
for(register int k = j; k < j + ll; ++k){
complex <double> x = a[k];
complex <double> y = w * a[k + ll];
a[k] = x + y;
a[k + ll] = x - y;
w = w * wn;
}
}
}
}
inline void ifft(complex <double> a[], int len){
fft(a, len); reverse(a + 1, a + len);
for(register int i = 0; i < len; ++i)a[i].imag(a[i].imag() / len);
}
inline void getrev(int len){
for(register int i = 0; i < len; ++i){
rev[i] = rev[i >> 1] >> 1;
if(i & 1)rev[i] |= len >> 1;
}
}
四次mtt
mtt
const ld PI = acos(-1);
struct comp{
ld x, y;
friend comp operator * (const comp &x, const comp &y){return {x.x * y.x - x.y * y.y, x.x * y.y + x.y * y.x};}
friend comp operator + (const comp &x, const comp &y){return {x.x + y.x, x.y + y.y};}
friend comp operator - (const comp &x, const comp &y){return {x.x - y.x, x.y - y.y};}
friend comp operator / (const comp &x, const ld &n){return {x.x / n, x.y / n};}
friend comp operator * (const comp &x, const ld &n){return {x.x * n, x.y *n};}
void operator /= (const ld &n){x /= n; y /= n;}
comp conj(){return {x, -y};}
}wn[maxn], I = {0, 1};
int deg, rev[maxn];
void init(int len){
deg = 1; while(deg < len)deg <<= 1;
wn[0] = {1, 0};
for(int i = 1; i < deg; ++i){
wn[i] = {cos(2.0 * PI * i / deg), sin(2.0 * PI * i / deg)};
rev[i] = rev[i >> 1] >> 1;
if(i & 1)rev[i] |= (deg >> 1);
}
}
struct poly{
comp f[maxn];
comp &operator [](const int &i){return f[i];}
void fft(){
for(int i = 1; i < deg; ++i)if(i < rev[i])swap(f[i], f[rev[i]]);
for(int l = 2, hl = 1; l <= deg; l <<= 1, hl <<= 1)
for(int i = 0; i < deg; i += l){
comp x, y;
for(int j = i; j < i + hl; ++j){
x = f[j], y = wn[deg / l * (j - i)] * f[j + hl];
f[j] = x + y; f[j + hl] = x - y;
}
}
}
void ifft(){fft(); reverse(f + 1, f + deg); for(int i = 0; i < deg; ++i)f[i] /= deg;}
}a0, a1, b0, b1, p, q;
void FFT(poly &x, poly &y){
for(int i = 0; i < deg; ++i)x[i] = {x[i].x, y[i].x}; x.fft();
for(int i = 0; i < deg; ++i)y[i] = x[i ? deg - i : 0].conj();
for(int i = 0; i < deg; ++i){comp a = x[i], b = y[i]; x[i] = (a + b) * 0.5; y[i] = (b - a) * 0.5 * I;}
}
int n, m, mod, base, ans[maxn];
ll num(ld x){return x > 0 ? ((ll)(x + 0.5)) % mod : ((ll)(x - 0.5)) % mod;}
int main(){
n = read(), m = read(); mod = read(); base = sqrt(mod) + 1; init(n + m + 1);
for(int i = 0; i <= n; ++i){int x = read() % mod; a0[i].x = x / base; a1[i].x = x % base;} FFT(a0, a1);
for(int i = 0; i <= m; ++i){int x = read() % mod; b0[i].x = x / base; b1[i].x = x % base;} FFT(b0, b1);
for(int i = 0; i < deg; ++i)p[i] = I * a0[i] * b0[i] + a1[i] * b0[i], q[i] = a0[i] * b1[i] + I * a1[i] * b1[i];
p.ifft(); q.ifft();
for(int i = 0; i <= n + m; ++i)printf("%lld ",(num(p[i].y) * base % mod * base % mod + (num(p[i].x) + num(q[i].x)) % mod * base % mod + num(q[i].y)) % mod);
printf("\n"); return 0;
}
ntt
const int mod = 998244353;
ll qpow(ll x, ll y){
ll ans = 1;
for(; y; y >>= 1, x = x * x % mod) if(y & 1) ans = ans * x % mod;
return ans;
}
inline void getrev(int len){
for(register int i = 0; i < len; ++i){
rev[i] = rev[i >> 1] >> 1;
if(i & 1)rev[i] |= len >> 1;
}
}
inline void ntt(ll a[], int len){
for(int i = 1; i < len; ++i)if(i < rev[i]) swap(a[i], a[rev[i]]);
for(int l = 2; l <= len; l <<= 1){
ll wn = qpow(3, (mod - 1) / l), p = l >> 1;
for(int j = 0; j < len; j += l){
ll w = 1;
for(int k = j; k < j + p; ++k){
ll x = a[k], y = w * a[k + p] % mod;
a[k] = (x + y) % mod; a[k + p] = (x - y + mod) % mod;
w = w * wn % mod;
}
}
}
}
inline void intt(ll a[], int len){
ntt(a, len); reverse(a + 1, a + len);
int inv = qpow(len, mod - 2);
for(int i = 0; i < len; ++i)a[i] = a[i] * inv % mod;
}
vector 封装 多项式 加 减 乘 除 模 求逆 开方 对数 指数
poly
int qpow(int x, int y){
int ans = 1;
for(; y; y >>= 1, x = 1ll * x * x % mod)if(y & 1)ans = 1ll * ans * x % mod;
return ans;
}
void add(int &x, int y){x += y; if(x >= mod)x -= mod;}
int rev[maxn], deg, wn[maxn];
void init(int len){
deg = 1; while(deg < len)deg <<= 1;
wn[0] = 1; wn[1] = qpow(3, (mod - 1) / deg);
for(int i = 1; i < deg; ++i){
rev[i] = (rev[i >> 1] >> 1);
if(i & 1)rev[i] |= (deg >> 1);
wn[i] = 1ll * wn[i - 1] * wn[1] % mod;
}
}
struct poly{
vector<int>f;
int &operator [](const int &i){return f[i];}
int operator [](const int &i)const{return f[i];}
void set(int n){f.resize(n);}
int si(){return f.size();}
int si()const{return f.size();}
void adj(){while(f.size() && f.back() == 0)f.pop_back();}
poly operator << (const int &x){poly ans; ans.set(x); for(int v : f)ans.f.push_back(v); return ans;}
poly operator >> (const int &x){poly ans; for(int i = x; i < si(); ++i)ans.f.push_back(f[i]); return ans;}
void ntt(){
for(int i = 1; i < deg; ++i)if(i < rev[i])swap(f[i], f[rev[i]]);
for(int l = 2, hl = 1; l <= deg; l <<= 1, hl <<= 1){
for(int i = 0; i < deg; i += l){
for(int j = i, x, y; j < i + hl; ++j){
x = f[j], y = 1ll * wn[deg / l * (j - i)] * f[j + hl] % mod;
f[j] = (x + y) % mod; f[j + hl] = (x - y + mod) % mod;
}
}
}
}
void intt(){
ntt(); reverse(f.begin() + 1, f.end()); int Inv = qpow(deg, mod - 2);
for(int i = 0; i < deg; ++i)f[i] = 1ll * f[i] * Inv % mod;
}
friend poly operator + (poly x, const poly &y){
x.set(max(x.si(), y.si()));
for(int i = 0; i < y.si(); ++i)add(x[i], y[i]);
return x;
}
void operator += (const poly &x){
set(max(x.si(), si()));
for(int i = 0; i < x.si(); ++i)add(f[i], x[i]);
}
friend poly operator - (poly x, const poly &y){
x.set(max(x.si(), y.si()));
for(int i = 0; i < y.si(); ++i)add(x[i], mod - y[i]);
return x;
}
void operator -= (const poly x){
set(max(x.si(), si()));
for(int i = 0; i < x.si(); ++i)add(f[i], mod - x[i]);
}
friend poly operator * (poly x, poly y){
poly ans; init(x.si() + y.si() - 1);
x.set(deg); y.set(deg); ans.set(deg); x.ntt(); y.ntt();
for(int i = 0; i < deg; ++i)ans[i] = 1ll * x[i] * y[i] % mod;
ans.intt(); ans.adj(); return ans;
}
void operator *= (poly x){
init(x.si() + si() - 1); x.set(deg); set(deg); x.ntt(); ntt();
for(int i = 0; i < deg; ++i)f[i] = 1ll * f[i] * x[i] % mod;
intt(); adj();
}
void reve(){reverse(f.begin(), f.end());}
friend poly operator / (poly x, poly y){
int s = x.si() - y.si() + 1;
x.reve(); y.reve(); y.set(s);
y = y.inv(); y *= x; y.set(s);
y.reve(); return y;
}
friend pair<poly, poly> operator % (poly x, poly y){
poly z = x / y;
poly r = x - y * z;
r.set(y.si() - 1);
return {z, r};
}
poly inv(){
poly ans; ans.set(1); ans[0] = qpow(f[0], mod - 2); poly a, b;
for(int len = 2; len < si() + si(); len <<= 1){
a.set(min(si(), len)); b = ans;
for(int i = 0; i < a.si(); ++i)a[i] = f[i];
init(a.si() + a.si() - 1); a.set(deg); b.set(deg); ans.set(deg);
a.ntt(); b.ntt();
for(int i = 0; i < deg; ++i)ans[i] = (2 - 1ll * a[i] * b[i] % mod + mod) % mod * b[i] % mod;
ans.intt(); ans.set(len);
}
ans.set(si()); return ans;
}
poly sqrt(){
poly ans, a; ans.set(1); ans[0] = 1; int inv2 = (mod + 1) >> 1;
for(int len = 2; len < si() + si(); len <<= 1){
int nl = min(len, si()); ans.set(len); a.set(nl);
for(int i = 0; i < nl; ++i)a[i] = f[i]; a *= ans.inv();
for(int i = 0; i < nl; ++i)ans[i] = 1ll * (ans[i] + a[i]) * inv2 % mod;
}
ans.set(si()); return ans;
}
void der(){for(int i = 1; i < f.size(); ++i)f[i - 1] = 1ll * f[i] * i % mod; f.back() = 0;}
poly Der(){poly g; g.f = f; g.der(); return g;}
void inte(){for(int i = f.size() - 1; i > 0; --i)f[i] = 1ll * f[i - 1] * qpow(i, mod - 2) % mod; f[0] = 0;}
poly Inte(){poly g; g.f = f; g.inte(); return g;}
poly ln(){
poly ans = inv(); ans *= (*this).Der();
ans.inte(); ans.set(si()); return ans;
}
poly exp(){
poly ans, a, b; ans.set(1); ans[0] = 1;
for(int len = 2; len < si() + si(); len <<= 1){
ans.set(len); a = ans.ln();
b.set(min(si(), len));
for(int i = 0; i < b.si(); ++i)b[i] = f[i];
b -= a; ++b[0]; ans *= b; ans.set(len);
}
ans.set(si()); return ans;
}
poly pow(int n){
poly ans; ans = ln();
for(int i = 0; i < si(); ++i)ans[i] = 1ll * ans[i] * n % mod;
return ans.exp();
}
};
树形结构
左偏树
#include<cstring>
#include<algorithm>
#include<queue>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int read(){
int x = 0; char c = getchar();
while(!isdigit(c))c = getchar();
do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
return x;
}
const int maxn = 100005;
int n, m;
int son[maxn][2], dis[maxn], f[maxn];
bool del[maxn];
struct node{
int id, val;
friend bool operator < (const node &x, const node &y){
return x.val == y.val ? x.id < y.id : x.val < y.val;
}
}d[maxn];
int fa(int x){return f[x] == x ? x : f[x] = fa(f[x]);}
int merge(int x, int y){
if(!x || !y)return x | y;
if(d[y] < d[x])swap(x, y);
son[x][1] = merge(son[x][1], y);
if(dis[son[x][1]] > dis[son[x][0]])swap(son[x][1], son[x][0]);
dis[x] = dis[son[x][1]] + 1;
return x;
}
int main(){
n = read(), m = read();
for(int i = 1; i <= n; ++i)d[i].val = read(), d[i].id = i, f[i] = i;
for(int op = 1; op <= m; ++op){
int opt, x;
opt = read(), x = read();
if(opt & 1){
int y = read();
if(del[x] || del[y])continue;
x = fa(x); y = fa(y);
if(x == y)continue;
f[x] = f[y] = merge(x, y);
}else{
if(del[x]){
printf("-1\n"); continue;
}
x = fa(x);
printf("%d\n",d[x].val);
del[x] = 1;
f[son[x][0]] = f[son[x][1]] = f[x] = merge(son[x][0], son[x][1]);
son[x][0] = son[x][1] = dis[x] = 0;
}
}
return 0;
}
splay
struct splay_tree{
#define ls t[x].son[0]
#define rs t[x].son[1]
#define son(x) (t[t[x].fa].son[1]==x)
struct node{
int son[2],fa,size,val,cnt;
}t[maxn];
int tot,root;
int New(int val,int fa){t[++tot].val=val;t[tot].cnt=t[tot].size=1;t[tot].fa=fa;return tot;}
void push_up(int x){t[x].size=t[ls].size+t[rs].size+t[x].cnt;}
void rotate(int x){
int f=t[x].fa,ff=t[f].fa,s=son(x),ss=son(f);
t[f].son[s]=t[x].son[s^1];
t[t[x].son[s^1]].fa=t[x].son[s^1]?f:0;
t[x].son[s^1]=f;t[f].fa=x;t[x].fa=ff;
t[ff].son[ss]=ff?x:0;
push_up(f);push_up(x);
}
void splay(int x){
for(int f=t[x].fa;f=t[x].fa;rotate(x))
if(t[f].fa)rotate(son(x)==son(f)?f:x);
root=x;
}
void insert(int val){
if(!root)return root=New(val,0),void();
int x=root;
while(1){
if(t[x].val==val)return ++t[x].cnt,push_up(x),splay(x),void();
int y=x;x=t[y].son[val>t[y].val];
if(!x)return t[y].son[val>t[y].val]=New(val,y),push_up(y),splay(tot),void();
}
}
int kth(int th){
int x=root;
while (1){
if(t[ls].size<th&&t[ls].size+t[x].cnt>=th)return splay(x),t[x].val;
if(th<=t[ls].size)x=ls;
else th-=t[ls].size+t[x].cnt,x=rs;
}
}
void erase(int val){
insert(val);
if(t[root].cnt>2)return t[root].cnt-=2,push_up(root),void();
int x=root;int sl=ls,sr=rs;
ls=rs=t[ls].fa=t[rs].fa=0;
if(!sl||!sr)return root=sl|sr,void();
else root=sl,kth(t[sl].size),t[root].son[1]=sr,t[sr].fa=root,push_up(root);
}
int rank(int val){insert(val);int ans=t[t[root].son[0]].size+1;erase(val);return ans;}
int pre(int val){insert(val);int ans=kth(t[t[root].son[0]].size);erase(val);return ans;}
int nxt(int val){insert(val);int ans=kth(t[t[root].son[0]].size+t[root].cnt+1);erase(val);return ans;}
}T;
LCT
struct LCT{
#define son(x) (x == t[t[x].fa].son[1])
#define lson t[x].son[0]
#define rson t[x].son[1]
struct node{
int son[2], fa, size, val, sum, lazy;
}t[maxn];
int cnt;
int isroot(int x){return t[t[x].fa].son[0] != x && t[t[x].fa].son[1] != x;}
int newnode(int val, int fa){
++cnt;
t[cnt].size = 1;
t[cnt].fa = fa;
t[cnt].val = val;
t[cnt].sum = val;
return cnt;
}
void push_up(int x){
t[x].size = t[lson].size + t[rson].size + 1;
t[x].sum = t[lson].sum ^ t[rson].sum ^ t[x].val;
}
void push_down(int x){
if(!t[x].lazy)return;
swap(t[lson].son[0], t[lson].son[1]);
swap(t[rson].son[0], t[rson].son[1]);
t[lson].lazy ^= 1; t[rson].lazy ^= 1; t[x].lazy ^= 1;
}
void spread(int x){
if(!isroot(x))spread(t[x].fa);
push_down(x);
}
void rotate(int x){
int f = t[x].fa, ff = t[f].fa, s = son(x), ss = son(f);
if(!isroot(f))t[ff].son[ss] = x;
t[f].son[s] = t[x].son[s ^ 1];
t[t[x].son[s ^ 1]].fa = t[x].son[s ^ 1] ? f : 0;
t[x].son[s ^ 1] = f;
t[f].fa = x;
t[x].fa = ff;
push_up(f);
push_up(x);
}
void splay(int x){
spread(x);
for(int f = t[x].fa; !isroot(x); rotate(x) , f = t[x].fa)
if(!isroot(f))rotate(son(f) == son(x) ? f : x);
}
int access(int x){
int p;
for(p = 0; x; p = x, x = t[x].fa){
splay(x); rson = p, push_up(x);
}
return p;
}
void makeroot(int x){
x = access(x);
swap(lson, rson);
t[x].lazy ^= 1;
}
int findroot(int x){
access(x);
splay(x);
push_down(x);
while(lson)x = lson, push_down(x);
splay(x);
return x;
}
void link(int x, int y){
if(findroot(x) == findroot(y))return;
makeroot(x);
splay(x);
t[x].fa = y;
}
void split(int x, int y){
makeroot(x);
access(y);
splay(y);
}
void cut(int x, int y){
split(x, y);
if(t[y].son[0] != x)return;
t[x].fa = t[y].son[0] = 0; push_up(y);
}
}T;
FHQ
struct FHQ_Treap{
struct node{
int l,r,size,val,key;
}t[maxn];
int tot,root;
int New(int x){t[++tot].val=x;t[tot].key=rand();t[tot].size=1;return tot;}
void push_up(int x){t[x].size=t[t[x].l].size+t[t[x].r].size+1;}
void split(int x,int &rtx,int &rty,int val){
if(x==0)return rtx=rty=0,void();
if(val<t[x].val){split(t[x].l,rtx,t[x].l,val);rty=x;push_up(rty);return;}
else{split(t[x].r,t[x].r,rty,val);rtx=x;push_up(rtx);return;}
}
int merge(int x,int y){
if(!x||!y)return x|y;
if(t[x].key<t[y].key){t[x].r=merge(t[x].r,y);push_up(x);return x;}
else{t[y].l=merge(x,t[y].l);push_up(y);return y;}
}
void insert(int x){
int l=0,r=0;split(root,l,r,x);
root=merge(merge(l,New(x)),r);
}
void erase(int x){
int l,m,r;split(root,l,r,x);split(l,l,m,x-1);
m=merge(t[m].l,t[m].r);
root=merge(merge(l,m),r);
}
int kth(int x,int id){
if(t[t[x].l].size+1==id)return t[x].val;
if(t[t[x].l].size>=id)return kth(t[x].l,id);
return kth(t[x].r,id-t[t[x].l].size-1);
}
int rank(int x){
int l=0,r=0,ans=0;
split(root,l,r,x-1);
ans=t[l].size+1;
root=merge(l,r);
return ans;
}
int pre(int x){
int l=0,r=0,ans=0;
split(root,l,r,x-1);
ans=kth(l,t[l].size);
root=merge(l,r);
return ans;
}
int nxt(int x){
int l=0,r=0,ans=0;
split(root,l,r,x);
ans=kth(r,1);
root=merge(l,r);
return ans;
}
}T;
Treap
struct Treap{
struct node{
int l,r,val,key,siz,cnt;
}t[maxn];
int tot,root;
int New(int x){
t[++tot].val=x;
t[tot].key=rand();
t[tot].siz=t[tot].cnt=1;
return tot;
}
void push_up(int x){t[x].siz=t[t[x].l].siz+t[t[x].r].siz+t[x].cnt;}
void zig(int &x){
int y=t[x].l;
t[x].l=t[y].r;
t[y].r=x;
x=y;
push_up(t[x].r);
push_up(x);
}
void zag(int &x){
int y=t[x].r;
t[x].r=t[y].l;
t[y].l=x;
x=y;
push_up(t[x].l);
push_up(x);
}
void insert(int &x,int val){
if(x==0)return x=New(val),void();
if(t[x].val==val)return ++t[x].cnt,++t[x].siz,void();
if(val<t[x].val){
insert(t[x].l,val);
push_up(x);
if(t[x].key<t[t[x].l].key)return zig(x);
}
if(val>t[x].val){
insert(t[x].r,val);
push_up(x);
if(t[x].key<t[t[x].r].key)return zag(x);
}
}
void erase(int &x,int val){
if(x==0)return;
if(t[x].val==val){
if(t[x].cnt>1)return --t[x].cnt,--t[x].siz,void();
if(!t[x].l&&!t[x].r)return x=0,void();
if(!t[x].r||t[t[x].l].key>t[t[x].r].key)return zig(x),erase(t[x].r,val),push_up(x);
if(!t[x].l||t[t[x].l].key<t[t[x].r].key)return zag(x),erase(t[x].l,val),push_up(x);
}
if(val<t[x].val)erase(t[x].l,val);
else erase(t[x].r,val);
push_up(x);
}
int rank(int x,int val){
if(x==0)return 0;
if(t[x].val==val)return t[t[x].l].siz;
if(t[x].val<val)return rank(t[x].r,val)+t[t[x].l].siz+t[x].cnt;
else return rank(t[x].l,val);
}
int pre(int val){
int x=root,ans=-2147483645;
while(x){
if(t[x].val<val)ans=max(ans,t[x].val),x=t[x].r;
else x=t[x].l;
}
return ans;
}
int next(int val){
int x=root,ans=2147483647;
while(x){
if(t[x].val>val)ans=min(ans,t[x].val),x=t[x].l;
else x=t[x].r;
}
return ans;
}
int kth(int x,int th){
if(th<=t[t[x].l].siz)return kth(t[x].l,th);
if(th<=t[t[x].l].siz+t[x].cnt)return t[x].val;
return kth(t[x].r,th-t[t[x].l].siz-t[x].cnt);
}
void print(int x){
if(t[x].l)print(t[x].l);
printf("%d ",t[x].val);
if(t[x].r)print(t[x].r);
}
}T;
笛卡尔树
for(int i = 1; i <= n; ++i){
int k = top;
while(k && a[st[k]] < a[i])--k;
if(k)rs[st[k]] = i;
if(k < top)ls[i] = st[k + 1];
st[++k] = i; top = k;
}
图论
支配树
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
int read(){
int x = 0; char c = getchar();
while(!isdigit(c))c = getchar();
do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
return x;
}
const int maxn = 3e5 + 55, inf = 0x3f3f3f3f;
int n, m, ans[maxn], zp[maxn], bzp[maxn];
vector<int>g1[maxn], g2[maxn], t[maxn];
int fa[maxn], dfn[maxn], id[maxn], tim;
struct DSU{
int f[maxn], val[maxn];
void init(){for(int i = 1; i <= n; ++i)f[i] = val[i] = i;}
int fa(int x){
if(f[x] == x)return x;
int nf = fa(f[x]);
if(dfn[bzp[val[f[x]]]] < dfn[bzp[val[x]]])val[x] = val[f[x]];
return f[x] = nf;
}
void merge(int x, int fx){f[x] = fx;}
int query(int x){fa(x); return val[x];}
}s;
void dfs(int x){
id[dfn[x] = ++tim] = x;
for(int v : g1[x])if(!dfn[v])fa[v] = x, dfs(v);
}
void solve(){
dfs(1); s.init();
for(int i = 1; i <= n; ++i)bzp[i] = zp[i] = i;
for(int i = n; i >= 1; --i){
int now = id[i];
for(int v : t[now]){
int tmp = s.query(v);
zp[v] = now == bzp[tmp] ? now : tmp;
}
for(int v : g2[now]){
if(!dfn[v])continue;
int tmp = s.query(v);
if(dfn[bzp[tmp]] < dfn[bzp[now]])bzp[now] = bzp[tmp];
}
t[bzp[now]].push_back(now);
t[now].clear();
s.merge(now, fa[now]);
}
for(int i = 2; i <= n; ++i){
int now = id[i];
if(zp[now] != bzp[now])zp[now] = zp[zp[now]];
}
}
int main(){
n = read(), m = read();
for(int i = 1; i <= m; ++i){
int u = read(), v = read();
g1[u].push_back(v);
g2[v].push_back(u);
}
solve();
for(int i = n; i >= 2; --i)ans[zp[id[i]]] += ++ans[id[i]];
++ans[1];
for(int i = 1; i <= n; ++i)printf("%d ",ans[i]); printf("\n");
return 0;
}
dinic
typedef long long ll;
const ll inf = 1e15;
const int maxn = 205;
const int maxm = 10005;
int n, m;
struct WWL{
int s, t;
int head[maxn], tot = 1;
struct edge{int to, net; ll val;}e[maxm];
void add(int u, int v, int w){
e[++tot].net = head[u];
head[u] = tot;
e[tot].to = v;
e[tot].val = w;
}
void link(int u, int v, int w){add(u, v, w); add(v, u, 0);}
int dep[maxn], now[maxn];
bool bfs(){
memset(dep, 0, sizeof(dep));
queue<int>q; dep[s] = 1; q.push(s);
now[s] = head[s];
while(!q.empty()){
int x = q.front(); q.pop();
for(int i = head[x]; i; i = e[i].net){
int v = e[i].to;
if(e[i].val > 0 && dep[v] == 0){
dep[v] = dep[x] + 1;
now[v] = head[v];
if(v == t)return true;
q.push(v);
}
}
}
return false;
}
ll dfs(int x, ll from){
if(x == t || from <= 0)return from;
ll res = from; int i;
for(i = now[x]; i; i = e[i].net){
int v = e[i].to;
if(e[i].val > 0 && dep[v] == dep[x] + 1){
ll k = dfs(v, min(res, e[i].val));
if(k <= 0)dep[v] = 0;
e[i].val -= k;
e[i ^ 1].val += k;
res -= k;
if(res <= 0)break;
}
}
now[x] = i;
return from - res;
}
ll dinic(){
ll ans = 0;
while(bfs())ans += dfs(s, inf);
return ans;
}
void init(){
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i = 1; i <= m; ++i){
int u, v, w; scanf("%d%d%d",&u,&v,&w);
link(u, v, w);
}
printf("%lld\n",dinic());
}
}w;
mcmf
struct MCMF{
int s, t;
int head[maxn], tot = 1;
struct edge{int to, net; ll val, cost;}e[maxm];
void add(int u, int v, int w, int c){
e[++tot] = {v, head[u], w, c};
head[u] = tot;
}
void link(int u, int v, int w, int c){add(u, v, w, c); add(v, u, 0, -c);}
bool vis[maxn]; queue<int>q; ll dis[maxn];
bool spfa(){
for(int i = 1; i <= n; ++i)dis[i] = inf, vis[i] = false;
vis[s] = true; dis[s] = 0; q.push(s);
while(!q.empty()){
int x = q.front(); q.pop();
vis[x] = false;
for(int i = head[x]; i; i = e[i].net){
int v = e[i].to;
if(e[i].val > 0 && dis[v] > dis[x] + e[i].cost){
dis[v] = dis[x] + e[i].cost;
if(!vis[v])q.push(v), vis[v] = true;
}
}
}
return dis[t] != inf;
}
ll dfs(int x, ll from){
if(x == t || from <= 0)return from;
vis[x] = true; ll res = from;
for(int i = head[x]; i; i = e[i].net){
int v = e[i].to;
if(!vis[v] && e[i].val > 0 && dis[v] == dis[x] + e[i].cost){
ll k = dfs(v, min(res, e[i].val));
e[i].val -= k;
e[i ^ 1].val += k;
res -= k;
if(res <= 0)break;
}
}
return from - res;
}
ll flow, cost;
void mcmf(){
while(spfa()){
ll k = dfs(s, inf);
flow += k; cost += k * dis[t];
}
}
void init(){
n = read(), m = read(), s = read(), t = read();
for(int i = 1; i <= m; ++i){
int u = read(), v = read(), w = read(), c = read();
link(u, v, w, c);
}
mcmf();
printf("%lld %lld\n",flow, cost);
}
}w;
斯坦纳树
typedef pair<int, int> pii;
priority_queue<pii, vector<pii>, greater<pii>>q;
int dp[maxn][1025];
bool vis[maxn];
void dij(int s){
memset(vis, 0, sizeof(vis));
while(!q.empty()){
int x = q.top().second;
q.pop();
if(vis[x])continue;
vis[x] = 1;
for(int i = head[x]; i; i = e[i].net){
int v = e[i].to;
if(dp[v][s] > dp[x][s] + e[i].val){
dp[v][s] = dp[x][s] + e[i].val;
q.push(pii(dp[v][s], v));
}
}
}
}
int main(){
n = read(), m = read(), k = read();
for(int i = 1; i <= m; ++i){
int u = read(), v = read(), w = read();
add(u, v, w); add(v, u ,w);
}
for(int i = 1; i <= k; ++i)ts[i] = read();
memset(dp, 0x3f, sizeof(dp));
for(int i = 1; i <= k; ++i)dp[ts[i]][1 << (i - 1)] = 0;
for(int s = 1; s < (1 << k); ++s){
for(int i = 1; i <= n; ++i){
for(int x = s & (s - 1); x; x = s & (x - 1))
dp[i][s] = min(dp[i][s], dp[i][x] + dp[i][s xor x]);
if(dp[i][s] != dp[0][0]){q.push(pii(dp[i][s], i));}
}
dij(s);
}
printf("%d\n",dp[ts[1]][(1 << k) - 1]);
return 0;
}
2-sat
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
int read(){
int x = 0; char c = getchar();
while(!isdigit(c))c = getchar();
do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
return x;
}
const int maxn = 2e6 + 55;
int n, m;
vector<int>g[maxn];
int dfn[maxn], low[maxn], tim, st[maxn], top, bl[maxn], cnt;
bool vis[maxn];
void tarjan(int x){
dfn[x] = low[x] = ++tim; vis[x] = true; st[++top] = x;
for(int v : g[x])
if(!dfn[v])tarjan(v), low[x] = min(low[x], low[v]);
else if(vis[v])low[x] = min(low[x], dfn[v]);
if(low[x] == dfn[x]){
bl[x] = ++cnt;
while(st[top] != x)bl[st[top]] = cnt, vis[st[top--]] = false;
vis[x] = false; --top;
}
}
int main(){
n = read(), m = read();
for(int i = 1; i <= m; ++i){
int u = read(), a = read(), v = read(), b = read();
g[u + (!a) * n].push_back(v + b * n);
g[v + (!b) * n].push_back(u + a * n);
}
for(int i = 1; i <= (n << 1); ++i)if(!dfn[i])tarjan(i);
for(int i = 1; i <= n; ++i)if(bl[i] == bl[i + n]){printf("IMPOSSIBLE\n"); return 0;}
printf("POSSIBLE\n");
for(int i = 1; i <= n; ++i)printf("%d ",bl[i + n] < bl[i]);
return 0;
}
字符串
pam
#include<cstring>
#include<iostream>
using namespace std;
const int maxn = 5e5+55;
char s[maxn];
int ch[maxn][27], len[maxn], fail[maxn], dep[maxn];
int main(){
cin >> s + 1;
s[0] = '#';
int n = strlen(s + 1);
int las = 0, ans = 0, cnt = 1;
fail[0] = 1;len[1] = -1;
for(int i = 1 ; i <= n; ++i){
while(s[i - len[las] - 1] != s[i])las = fail[las];
if(!ch[las][s[i] - 'a']){
len[++cnt] = len[las] + 2;
int j = fail[las];
while(s[i - len[j] - 1] != s[i])j = fail[j];
fail[cnt] = ch[j][s[i] - 'a'];
ch[las][s[i] - 'a'] = cnt;
}
las = ch[las][s[i] - 'a'];
cout << (ans = dep[las]) << " " ;
}
return 0;
}
sa
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f;
const int maxn=1000005;
char s[maxn];
int n,w,sa[maxn],rk[maxn<<1|1],id[maxn],m=300,oldrk[maxn<<1|1],cnt[maxn],px[maxn];
bool cmp(int x,int y,int w){
return oldrk[x]==oldrk[y]&&oldrk[x+w]==oldrk[y+w];
}
void get_ht() {
for(int k=0,i=1;i<=n;++i){
if(rk[i]==1)continue;
if(k)--k;
while(s[i+k]==s[sa[rk[i]-1]+k])++k;
ht[rk[i]]=k;
}
}
int main(){
scanf("%s",s+1);
n=strlen(s+1);
for(int i=1;i<=n;++i)++cnt[rk[i]=s[i]];//按照第一个字母排个序,这个时候只需要相对大小关系,里面的东西暂时不太合法
for(int i=1;i<=m;++i)cnt[i]+=cnt[i-1];//桶累加
for(int i=n;i>=1;--i)sa[cnt[rk[i]]--]=i;//cnt[..]为i的新rank 其实是sa[rk[i]]=i
m=max(m,n);//m为桶的值域
for(w=1;w<n;w<<=1){
int p=0;
for(int i=n;i>n-w;--i)id[++p]=i;//空串直接记录,按照第二关键字他们最小且没有顺序,所以随便给个顺序即可
for(int i=1;i<=n;++i)if(sa[i]>w)id[++p]=sa[i]-w;//第二关键字,用后缀i的当前sa的顺序去更新后缀sa[i]-w
for(int i=1;i<=m;++i)cnt[i]=0;//清桶
for(int i=1;i<=n;++i)++cnt[px[i]=rk[id[i]]];//按照原来的rank排序,px临时存一下rk[id[i]],减少不必要的内存访问
for(int i=1;i<=m;++i)cnt[i]+=cnt[i-1];//累加
for(int i=n;i>=1;--i)sa[cnt[px[i]]--]=id[i];//cnt[..]为sa[i]的新rank 而为了避免改乱,所以原来的sa用id来代替,这就是上面和这里赋值用id的原因
for(int i=1;i<=n;++i)oldrk[i]=rk[i];//copy一下,cmp用
p=0;
for(int i=1;i<=n;++i)rk[sa[i]]=cmp(sa[i],sa[i-1],w)?p:++p;//写cmp减少不必要的内存访问,去重
if(p==n)break;//已经排完就不用管了
m=p;//值域优化
}
for(int i=1;i<=n;++i)printf("%d ",sa[i]);
return 0;
}
sam
struct SAM{
int cnt = 1, las = 1;
void add(int c){
int fa = las, now = las = ++cnt;
d[now].len = d[fa].len + 1;
f[now] = 1;
for(; fa && !d[fa].ch[c]; fa = d[fa].fa) d[fa].ch[c] = now;
if(!fa)d[now].fa = 1;
else{
int j = d[fa].ch[c];
if(d[j].len == d[fa].len + 1)d[now].fa = j;
else{
int clone = ++cnt;
d[clone] = d[j];
d[clone].len = d[fa].len + 1;
d[j].fa = d[now].fa = clone;
for(; fa && d[fa].ch[c] == j; fa = d[fa].fa)d[fa].ch[c] = clone;
}
}
}
}S;
general-sam
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 15e5 + 55;
char c[maxn];
struct node{
int len, fa, ch[26];
}d[maxn];
struct SAM{
int cnt = 1, las = 1;
void add(int c){
if(d[las].ch[c]){
int fa = las, x = d[las].ch[c];
if(d[fa].len + 1 == d[x].len)las = x;
else{
int now = las = ++cnt;
d[now] = d[x];
d[now].len = d[fa].len + 1;
for(; fa && d[fa].ch[c] == x; fa = d[fa].fa)d[fa].ch[c] = now;
d[x].fa = now;
}
}else{
int fa = las;
int now = las = ++cnt;
d[now].len = d[fa].len + 1;
for(; fa && !d[fa].ch[c]; fa = d[fa].fa)d[fa].ch[c] = now;
if(!fa)d[now].fa = 1;
else{
int x = d[fa].ch[c];
if(d[fa].len + 1 == d[x].len)d[now].fa = x;
else{
int clone = ++cnt;
d[clone] = d[x];
d[clone].len = d[fa].len + 1;
d[x].fa = d[now].fa = clone;
for(; fa && d[fa].ch[c] == x; fa = d[fa].fa)d[fa].ch[c] = clone;
}
}
}
}
}S;
int n;
int main(){
cin >> n;
for(int i = 1; i <= n; ++i){
cin >> c + 1;
int len = strlen(c + 1);
S.las = 1;
for(int i = 1; i <= len ; ++i)S.add(c[i] - 'a');
}
return 0;
}
AC
struct AC{
int root = 1, cnt = 1;
int ch[maxn][26],fail[maxn],size[maxn];
void insert(){
int len = strlen(c + 1), now = root;
for(int i = 1; i <= len; ++i)s[i] = c[i] - 'a';
for(int i = 1; i <= len; ++i){
if(!ch[now][s[i]])ch[now][s[i]] = ++cnt;
now = ch[now][s[i]];
}
++size[now];
}
queue<int>q;
void built(){
for(int i = 0; i < 26; ++i)
if(ch[root][i])fail[ch[root][i]] = root,q.push(ch[root][i]);
else ch[root][i] = root;
while(!q.empty()){
int x = q.front(); q.pop();
for(int i = 0; i < 26; ++i){
if(ch[x][i])fail[ch[x][i]] = ch[fail[x]][i], q.push(ch[x][i]);
else ch[x][i] = ch[fail[x]][i];
}
}
}
bool vis[maxn];
int match(){
int len = strlen(c + 1),now = root;
for(int i = 1; i <= len; ++i)s[i] = c[i] - 'a';
int ans = 0;
for(int i = 1; i <= len; ++i){
now = ch[now][s[i]];
if(!vis[now])ans += size[now], vis[now] = 1;
}
return ans;
}
}A;
manacher
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 22000005;
char c[maxn], s[maxn];
int p[maxn];
int main(){
scanf("%s",c + 1);
int n = strlen(c + 1), cnt = 0;
s[++cnt] = '~', s[++cnt] = '#';
for(int i = 1; i <= n; ++i)s[++cnt] = c[i], s[++cnt] = '#';
s[++cnt] = '!';
int mr = 0, mid = 0, ans = 0;
for(int i = 2; i < cnt; ++i){
if(i <= mr)p[i] = min(p[mid * 2 - i], mr - i + 1);
else p[i] = 1;
while(s[i - p[i]] == s[i + p[i]]) ++p[i];
if(i + p[i] > mr)mr = i + p[i] - 1, mid = i;
ans = max(ans, p[i]);
}
printf("%d\n",ans - 1);
return 0;
}
最小表示法
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 6e5 + 55;
int a[maxn], n;
int main(){
ios::sync_with_stdio(false);
cin >> n;
for(int i = 0; i < n; ++i)cin >> a[i];
for(int i = 0; i < n; ++i)a[i + n] = a[i];
int i = 0, j = 1, k = 0;
while(i < n && j < n && k < n){
if(a[(i + k) % n] == a[(j + k) % n])++k;
else{
if(a[(i + k) % n] > a[(j + k) % n])i = i + k + 1;
else j = j + k + 1;
if(i == j)++i;
k = 0;
}
}
int ans = min(i, j);
for(int i = 0; i < n; ++i)cout << a[(i + ans) % n] << " ";
return 0;
}
kmp
for(int i = 2, j = 0; i <= l2; ++i){
while(j && s2[j + 1] != s2[i])j = nxt[j];
if(s2[j + 1] == s2[i]) ++j;
nxt[i] = j;
}
for(int j = 0, i = 1; i <= l1; ++i){
while(j && s2[j + 1] != s1[i])j = nxt[j];
if(s2[j + 1] == s1[i]) ++j;
if(j == l2)printf("%d\n",i - l2 + 1), j = nxt[j];
}
excmp/z函数
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 2e7 + 55;
int nxt[maxn], ext[maxn];
char a[maxn], b[maxn];
void solvenxt(){
int len = strlen(b);
int p = 0, k = 1;
nxt[0] = len; while(p + 1 < len && b[p] == b[p + 1])++p;
nxt[1] = p;
for(int i = 2; i < len; ++i){
p = k + nxt[k] - 1;
int l = nxt[i - k];
if(i + l <= p)nxt[i] = l;
else{
int j = max(0, p - i + 1);
while(i + j < len && b[i + j] == b[j]) ++j;
nxt[i] = j;
k = i;
}
}
}
void exkmp(){
int la = strlen(a), lb = strlen(b);
int p = 0, k = 0;
while(p < la && p < lb && a[p] == b[p])++p;
ext[0] = p;
for(int i = 1; i < la; ++i){
p = k + ext[k] - 1;
int l = nxt[i - k];
if(i + l <= p)ext[i] = l;
else {
int j = max(0, p - i + 1);
while(i + j < la && j < lb && a[i + j] == b[j]) ++j;
ext[i] = j;
k = i;
}
}
}
int main(){
scanf("%s%s",a,b);
solvenxt();
exkmp();
int l = strlen(b);
ll ans = 0;
for(int i = 0; i < l; ++i)ans ^= (i + 1ll) * (nxt[i] + 1);
printf("%lld\n",ans);
ans = 0;
l = strlen(a);
for(int i = 0; i < l; ++i)ans ^= (i + 1ll) * (ext[i] + 1);
printf("%lld\n",ans);
return 0;
}
杂项
同下
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include<random>
using namespace std;
typedef unsigned long long ull;
mt19937 rd((ull)(new char) * (ull) (new char));
const int maxn = 10005;
int n, x[maxn], y[maxn], w[maxn];
double ansx, ansy, las;
double s(int l, int r){
uniform_real_distribution<>d(l, r);
return d(rd);
}
double check(double nx, double ny){
double nans = 0;
for(int i = 1; i <= n; ++i){
double dx = x[i] - nx, dy = y[i] - ny;
nans += sqrt(dx * dx + dy * dy) * w[i];
}
if(nans < las)las = nans, ansx = nx, ansy = ny;
return nans;
}
void sa(){
double t = 100000, down = 0.99;
double nx = ansx, ny = ansy;
while(t > 0.0001){
double nnx = nx + t * (s(0, 1) * 2 - 1);
double nny = ny + t * (s(0, 1) * 2 - 1);
double dt = check(nnx, nny) - check(nx, ny);
if(exp(-dt / t) > s(0, 1))nx = nnx, ny = nny;
t *= down;
}
for(int i = 1; i <= 10000; ++i){
double nnx = ansx + t * (s(0, 1) * 2 - 1);
double nny = ansy + t * (s(0, 1) * 2 - 1);
check(nnx, nny);
}
}
int main(){
scanf("%d",&n);
for(int i = 1; i <= n; ++i){
scanf("%d%d%d",&x[i], &y[i], &w[i]);
ansx += x[i], ansy += y[i];
}
ansx /= n, ansy /= n, las = check(ansx, ansy);
sa();sa();sa();sa();sa();
printf("%.3lf %.3lf\n",ansx, ansy);
return 0;
}
sa/模拟退火
int check(){
int nans = 0;
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= 3; ++j){
nans += abs(pos[i] - pos[f[i][j]]);
}
}
return nans / 2;
}
int s(int l, int r){
uniform_int_distribution<>d(l, r);
return d(rd);
}
void sa(){
double t = 100000, down = 0.99, t0 = 0.000001;
int x ,y, lans;
while(t > t0){
do{
x = s(1, n);
y = s(1, n);
}while(x == y);
swap(pos[x], pos[y]);
lans = check();
if(lans <= dis){
dis = lans;
}else if(exp((-lans + dis) / t < (double)s(0, INT_MAX) / INT_MAX))swap(pos[x], pos[y]);
t *= down;
}
return ;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】