如果这篇博客帮助到你,可以请我喝一杯咖啡~
CC BY 4.0 (除特别声明或转载文章外)
Made In Heaven
Astar 求 K 短路。
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
typedef int ll;
const ll INF = 1e9;
struct Graph
{
struct Vertex
{
vector<int> a, b; //相关出边和入边编号
//int siz,dep,top,dfn;//树链剖分中使用,依次代表子树节点数、深度、所在链的顶端节点、dfs序
};
struct Edge
{
int from, to;
ll dist /*,cap*/; //边长、容量,图论算法使用
};
vector<Vertex> v; //点集
vector<Edge> e; //边集
Graph(int n) : v(n) {}
void add(const Edge &ed)
{
//if(ed.from==ed.to)return;//如果有需要请拆点
v[ed.from].a.push_back(e.size());
v[ed.to].b.push_back(e.size());
e.push_back(ed);
}
};
struct Dijkstra : Graph
{
vector<ll> d;
Dijkstra(int n) : Graph(n) {}
void ask(int s)
{
d.assign(v.size(), INF);
priority_queue<pair<ll, int>> q;
for (q.push(make_pair(d[s] = 0, s)); !q.empty();)
{
ll dis = -q.top().first;
int u = q.top().second;
if (q.pop(), d[u] < dis)
continue;
for (int i = 0, k, to; i != v[u].a.size(); ++i)
if (k = v[u].a[i], to = e[k].to,
d[to] > d[u] + e[k].dist)
{
d[to] = d[u] + e[k].dist;
q.push(make_pair(-d[to], to));
}
}
}
};
struct Astar : Dijkstra
{
vector<ll> ans;
Astar(int n) : Dijkstra(n) {}
void ask(int s, int t, int k, int T)
{
Dijkstra::ask(s);
ans.assign(k, INF);
if (d[t] == INF)
return;
vector<int> cnt(v.size(), 0);
priority_queue<pair<ll, int>> q;
for (q.push(make_pair(-d[t], t)); cnt[s] < k && !q.empty();)
{
ll dis = -q.top().first;
int u = q.top().second;
if (u == s)
ans[cnt[s]] = dis;
if (dis > T)
return;
if (q.pop(), ++cnt[u] > k)
continue;
for (int i = 0, k; i < v[u].b.size(); ++i)
k = v[u].b[i], q.push(make_pair(d[u] - d[e[k].from] - e[k].dist - dis, e[k].from));
}
}
};
int main()
{
for (int n, m, s, e, k, t; ~scanf("%d%d%d%d%d%d", &n, &m, &s, &e, &k, &t);)
{
Astar g(n + 1);
for (int u, v, w; m--;)
{
scanf("%d%d%d", &u, &v, &w);
g.add({u, v, w});
}
g.ask(s, e, k, t);
printf(g.ans[k - 1] > t ? "Whitesnake!\n" : "yareyaredawa\n");
}
}
Fantastic Graph
转换一下变成一个有源汇上下界网络流模型。
#include <cstdio>
#include <vector>
using namespace std;
typedef int ll;
const ll INF = 1e9;
struct Graph
{
struct Vertex
{
vector<int> a /*,b*/; //相关出边和入边编号
//int siz,dep,top,dfn;//树链剖分中使用,依次代表子树节点数、深度、所在链的顶端节点、dfs序
};
struct Edge
{
int from, to;
ll /*dist,*/ cap; //边长、容量,图论算法使用
};
vector<Vertex> v; //点集
vector<Edge> e; //边集
Graph(int n) : v(n) {}
void add(const Edge &ed)
{
//if(ed.from==ed.to)return;//如果有需要请拆点
v[ed.from].a.push_back(e.size());
//v[ed.to].b.push_back(e.size());
e.push_back(ed);
}
};
struct ISAP : Graph
{
ll flow;
vector<ll> f;
vector<int> h, cur, gap;
ISAP(int n) : Graph(n) {}
void add(Edge ed)
{
Graph::add(ed);
swap(ed.from, ed.to), ed.cap = 0;
Graph::add(ed);
}
ll dfs(int s, int u, int t, ll r)
{
if (r == 0 || u == t)
return r;
ll _f, _r = 0;
for (int &i = cur[u], k; i < v[u].a.size(); ++i)
if (k = v[u].a[i], h[u] == h[e[k].to] + 1)
{
_f = dfs(s, e[k].to, t, min(r - _r, e[k].cap - f[k]));
f[k] += _f, f[k ^ 1] -= _f, _r += _f;
if (_r == r || h[s] >= v.size())
return _r;
}
if (!--gap[h[u]])
h[s] = v.size();
return ++gap[++h[u]], cur[u] = 0, _r;
}
void ask(int s, int t)
{
h.assign(v.size(), 0);
cur.assign(v.size(), 0);
gap.assign(v.size() + 2, 0);
/*for(deque<int> q(h[t]=gap[t]=1,t); !q.empty(); q.pop_front())//可选预处理
for(int i=0,u=q.front(),k,to; i<v[u].a.size(); ++i)
if(to=e[v[u].a[i]].to,!h[to])
++gap[h[to]=h[u]+1],q.push_back(to);*/
for (f.assign(e.size(), flow = 0); h[s] < v.size();)
flow += dfs(s, s, t, INF);
}
};
int main()
{
for (int n, m, k, l, r, kase = 0; ~scanf("%d%d%d", &n, &m, &k);)
{
ISAP g((n + m) * 2 + 9);
scanf("%d%d", &l, &r);
for (int i = 0, u, v; i < k; ++i)
{
scanf("%d%d", &u, &v);
v += n;
g.add({2 * u + 1, 2 * v, 1});
}
int s = 2 * (n + m + 1), t = s + 1, ss = t + 1, tt = ss + 1;
g.add({t, s, INF});
for (int i = 1; i <= n; ++i)
g.add({s, 2 * i, INF});
for (int i = n + 1; i <= n + m; ++i)
g.add({2 * i + 1, t, INF});
for (int i = 1; i <= n + m; ++i)
{
g.add({2 * i, 2 * i + 1, r - l});
g.add({ss, 2 * i + 1, l});
g.add({2 * i, tt, l});
}
g.ask(ss, tt);
printf("Case %d: %s\n", ++kase, g.flow == (n + m) * l ? "Yes" : "No");
}
}
Spare Tire
#include <cstdio>
#include <vector>
#define mul(a, b, m) ((a) * (b) % (m))
using namespace std;
typedef long long ll;
const ll M = 1e9 + 7;
ll n, m, ans1, ans2, INV[9];
vector<ll> fac;
void getfac(ll n)
{
fac.clear();
for (ll i = 2; i * i <= n; ++i)
if (n % i == 0)
for (fac.push_back(i); n % i == 0;)
n /= i;
if (n > 1)
fac.push_back(n);
}
ll pow(ll a, ll b, ll m)
{
ll r = 1;
for (a %= m; b; b >>= 1, a = mul(a, a, m))
if (b & 1)
r = mul(r, a, m);
return r;
}
void dfs(ll cur, ll num, ll val)
{
if (cur == fac.size())
{
if (val != 1)
{
ll t = n / val, k = mul(mul(t * (t + 1) / 2 % M, num % 2 ? M - 1 : 1, M), val, M);
if (ans1 += k, ans1 >= M)
ans1 -= M;
if (ans2 += mul(mul(mul(k, (t * 2 + 1), M), INV[3], M), val, M), ans2 >= M)
ans2 -= M;
}
return;
}
dfs(cur + 1, num, val), dfs(cur + 1, num + 1, val * fac[cur]);
}
int main()
{
for (ll i = 0; i < 9; ++i)
INV[i] = pow(i, M - 2, M);
while (~scanf("%lld%lld", &n, &m))
{
ans1 = n * (n + 1) / 2 % M;
ans2 = ans1 * (2 * n + 1) % M * INV[3] % M;
getfac(m);
dfs(0, 0, 1);
printf("%lld\n", (ans1 + ans2) % M);
}
}
Lattice’s basics in digital electronics
做了一遍就不想再做一遍的沙雕大模拟…为了模拟而模拟。字典树跑掉。
#include <cstdio>
using namespace std;
const int NPOS = -1, N = 200009 << 2;
struct AhoCorasick
{
struct Node
{
int ch[2], val;
int &to(char c)
{
return ch[c - '0'];
}
Node() : val(NPOS)
{
ch[0] = ch[1] = 0;
}
} v[N];
int siz;
AhoCorasick() : siz(1) {}
void add(char s[], int val)
{
int u = 0;
for (int i = 0; s[i]; u = v[u].to(s[i++]))
if (!v[u].to(s[i]))
{
v[u].to(s[i]) = siz;
v[siz++] = Node();
}
v[u].val = val;
}
};
char stak[N], data[N];
int t, kase = 0, m, n;
int main()
{
for (scanf("%d", &t); t--;)
{
scanf("%d%d", &m, &n);
AhoCorasick ac;
for (int i = 0, c; i < n; ++i)
{
scanf("%d%s", &c, data);
ac.add(data, c);
}
scanf("%s", stak);
int len = 0, siz = 0;
for (int i = 0; stak[i]; ++i)
{
stak[i] = '0' <= stak[i] && stak[i] <= '9' ? stak[i] - '0' : 'a' <= stak[i] && stak[i] <= 'z' ? stak[i] - 'a' + 10 : stak[i] - 'A' + 10;
len += 4;
for (int j = 1; j <= 4; ++j)
data[len - j] = '0' + stak[i] % 2, stak[i] /= 2;
}
for (int i = 0, cnt; i + 8 < len; i += 9)
{
for (int j = cnt = 0; j < 8; ++j)
if (data[i + j] == '1')
++cnt;
if (cnt % 2 != (data[i + 8] == '0' ? 1 : 0))
continue;
for (int j = 0; j < 8; ++j)
stak[siz++] = data[i + j];
}
for (int i = 0, u = 0, cnt = 0; i < siz; ++i)
if (ac.v[u = ac.v[u].to(stak[i])].val != NPOS)
{
printf("%c", ac.v[u].val);
u = 0;
if (++cnt == m)
break;
}
printf("\n");
}
}
Supreme Number
#include <stdio.h>
#include <string.h>
char s[127];
int t, n, kase, a[] = {1, 2, 3, 5, 7, 11, 13, 17, 23, 31, 37, 53, 71, 73, 113, 131, 137, 173, 311, 317};
int main()
{
for (scanf("%d", &t); t--;)
{
scanf("%s", s);
if (strlen(s) > 3)
n = 318;
else
sscanf(s, "%d", &n);
for (int i = 19; ~i; --i)
if (a[i] <= n)
{
printf("Case #%d: %d\n", ++kase, a[i]);
break;
}
}
}