版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
// 快读
inline const int read()
{
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + ch - '0'; ch = getchar(); }
return x * f;
}
// 快速幂
ll qpow(ll x, ll k)
{
ll res = 1;
while (k)
{
if (k & 1) res = res * x % mod;
x = x * x % mod; k >>= 1;
}
return res;
}
// 矩阵快速幂
// POJ3070 求斐波那契数列第n项取模
#include <iostream>
#include <cstring>
using namespace std;
const int mod = 10000;
const int v[4] = {0, 1, 1, 2};
struct matrix
{
int mat[3][3];
void init()
{
memset(mat, 0, sizeof(mat));
for (int i = 0; i < 3; i++) mat[i][i] = 1;
}
};
matrix mul(const matrix& a, const matrix& b)
{
matrix res;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
res.mat[i][j] = 0;
for (int k = 0; k < 3; k++) res.mat[i][j] = (res.mat[i][j] + a.mat[i][k] * b.mat[k][j]) % mod;
}
}
return res;
}
matrix quick_pow(matrix a, int n)
{
matrix res; res.init();
while (n)
{
if (n & 1) res = mul(res, a);
a = mul(a, a); n >>= 1;
}
return res;
}
int main()
{
matrix base;
memset(base.mat, 0, sizeof(base.mat));
base.mat[0][0] = base.mat[0][1] = base.mat[1][0] = base.mat[2][1] = 1;
int n;
while (cin >> n && n != -1)
{
if (n <= 3) cout << v[n] << endl;
else
{
matrix pow = quick_pow(base, n - 3);
int res = 0;
for (int i = 0; i < 3; i++) res = (res + pow.mat[0][i] * v[3 - i]) % mod;
cout << res << endl;
}
}
return 0;
}
// 威尔逊定理
// (p − 1)! == −1 (mod p)
// 若p为质数,则p可整除(p - 1)! + 1
// 费马小定理
// a ^ (p - 1) == 1 (mod p)
// 欧拉定理
// a ^ φ(m) == 1 (mod m) (gcd(a, m) == 1, m >= 2)
// 欧拉函数
// φ(n): 小于或等于n的正整数中与n互质的数目
// 1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6
// 欧拉函数 打表
void get_euler()
{
for (int i = 1; i < maxn; i++)
phi[i] = i;
for (int i = 2; i < maxn; i++)
if (phi[i] == i)
for (int j = i; j < maxn; j += i)
phi[j] = phi[j] / i * (i - 1);
}
// 欧拉函数 求值
ll euler(int n)
{
ll res = 1;
for (int i = 2; i <= sqrt(n); i++)
{
if (n % i == 0)
{
n /= i; res *= i - 1;
while (n % i == 0) { n /= i; res *= i; }
}
}
if (n > 1) res *= n - 1;
return res;
}
// 乘法逆元
// n在模p意义下的乘法逆元
// (1 / n) % p == n ^ (p - 2) % p
// 线性求乘法逆元
// inv[i] = (ll)(p - p / i) * inv[p % i] % p;
// Polya定理
// m颗珠子,n种颜色: L = (1 / m) * Σ(i = 1, m)(n ^ gcd(i, m))
// 当n == m: L = (1 / n) * Σ(p | n)(φ(p) * n ^ (n / p)) = Σ(p | n)(φ(p) * n ^ (n / p - 1))
// 链式前向星
int head[maxn];
struct edge { int v, w, next; } e[maxm];
void addEdge(int u, int v, int w)
{
e[cnt].v = v;
e[cnt].w = w;
e[cnt].next = head[u];
head[u] = cnt++;
}
// 最短路径 Dijkstra
struct node
{
int u, w;
bool operator < (const node& n) const { return w > n.w; }
};
priority_queue<node> q;
void dijkstra(int src)
{
memset(vis, false, sizeof(vis));
for (int i = 1; i <= n; i++) dis[i] = inf;
dis[src] = 0;
q.push(node{src, 0});
while (!q.empty())
{
int u = q.top().u; q.pop();
if (vis[u]) continue;
vis[u] = true;
for (int i = head[u]; ~i; i = e[i].next)
{
int v = e[i].v, w = e[i].w;
if (dis[v] > dis[u] + w)
{
dis[v] = dis[u] + w;
q.push(node{v, dis[v]});
}
}
}
}
// 最短路径 SPFA
void spfa(int src)
{
memset(vis, false, sizeof(vis));
for (int i = 1; i <= n; i++) dis[i] = inf;
dis[s] = 0;
queue<int> q;
q.push(s);
while (!q.empty())
{
int u = q.front(); q.pop();
vis[u] = false;
for (int i = head[u]; ~i; i = e[i].next)
{
int v = e[i].v, w = e[i].w;
if (dis[v] > dis[u] + w)
{
dis[v] = dis[u] + w;
if (!vis[v])
{
q.push(v);
vis[v] = true;
}
}
}
}
}
// 无向图找环 DFS
void dfs(int cur, int pre, int dep)
{
vis[cur] = 1; depth[cur] = dep;
for (int i = head[cur]; ~i; i = e[i].next)
{
int nxt = e[i].to;
if (nxt == pre) continue;
if (vis[nxt] == 0) dfs(nxt, cur, dep + 1);
else if (vis[nxt] == 1) loop[lpcnt++] = depth[cur] - depth[nxt] + 1;
}
vis[cur] = 2;
}
// 最近公共祖先(LCA) Tarjan离线
struct edge { int next, to; } e[maxm];
struct que { int next, to, id; } q[maxq];
void tarjan(int u)
{
vis[u] = true;
for (int i = ehead[u]; i != -1; i = e[i].next)
{
int v = e[i].to;
if (!vis[v])
{
tarjan(v);
Union(u, v);
}
}
for (int i = qhead[u]; i != -1; i = q[i].next)
{
int v = q[i].to;
if (vis[v]) ans[q[i].id] = Find(v);
}
}
// 强连通分量 Tarjan
// dfn[] 当前点的DFS遍历时间戳
// low[] 当前点及其所有子孙节点所能连接的点的最小dfn
// sta[] 当前所有可能构成强连通分量的点
// vis[] 当前点是否在sta[]中
void tarjan(int u)
{
vis[u] = true;
dfn[u] = low[u] = ++dep;
sta[top++] = u;
for (int i = head[u]; ~i; i = e[i].next)
{
int v = e[i].to;
if (!dfn[v])
{
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if (vis[v]) low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u])
{
color[u] = ++cnt;
vis[u] = false;
while (sta[--top] != u)
{
vis[sta[top]] = false;
color[sta[top]] = cnt;
}
}
}
// 割点 Tarjan
void tarjan(int cur, int pre)
{
int child = 0;
low[cur] = dfn[cur] = ++dep;
for (int i = head[cur]; ~i; i = e[i].next)
{
int nxt = e[i].to;
if (!dfn[nxt])
{
child++;
tarjan(nxt, cur);
low[cur] = min(low[cur], low[nxt]);
if (pre != cur && low[nxt] >= dfn[cur] && !iscut[cur])
{
ccnt++;
iscut[cur] = true;
}
}
else if (nxt != pre) low[cur] = min(low[cur], dfn[nxt]);
}
if (pre == cur && child >= 2)
{
ccnt++;
iscut[cur] = true;
}
}
// 二分图最大匹配 / 最小顶点覆盖 / 最小边覆盖 / 最大独立集 Hungary
// 最小顶点覆盖 = 二分图最大匹配 最小的顶点集合使二分图的每条边至少与其中一个点关联
// 最小边覆盖 = |V| - 二分图最大匹配 最小的边集合,覆盖二分图中所有顶点
// 最大独立集 = |V| - 二分图最大匹配 最大的顶点集合,其中任意两点在二分图中无对应边
// 洛谷P3386 【模板】二分图匹配
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 10;
int n, m, e, match[maxn];
bool vis[maxn], g[maxn][maxn];
inline const int read()
{
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + ch - '0'; ch = getchar(); }
return x * f;
}
bool dfs(int u)
{
for (int v = 1; v <= m; v++)
{
if (!vis[v] && g[u][v])
{
vis[v] = true;
if (!match[v] || dfs(match[v]))
{
match[v] = u;
return true;
}
}
}
return false;
}
int main()
{
n = read(); m = read(); e = read();
while (e--)
{
int a = read(), b = read();
if (a <= n && b <= m) g[a][b] = true;
}
int ans = 0;
for (int i = 1; i <= n; i++)
{
memset(vis, false, sizeof(vis));
ans += dfs(i);
}
printf("%d\n", ans);
return 0;
}
// K短路 A*
// POJ2449 Remmarguts' Date
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
const int maxn = 1e3 + 10, maxm = 1e5 + 10, inf = 1e9;
bool vis[maxn];
int n, m, s, t, k, tot;
int head1[maxn], head2[maxn], dis[maxn];
struct enode
{
int v, w, next;
} e1[maxm], e2[maxm];
struct anode
{
int id, f, g;
bool operator < (const anode &a) const
{
return f != a.f ? f > a.f : g > a.g;
}
};
inline const int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + ch - '0'; ch = getchar(); }
return x * f;
}
void addedge(int u, int v, int w)
{
++tot;
e1[tot].v = v; e1[tot].w = w; e1[tot].next = head1[u]; head1[u] = tot;
e2[tot].v = u; e2[tot].w = w; e2[tot].next = head2[v]; head2[v] = tot;
}
void spfa(int s)
{
for (int i = 1; i <= n; i++)
dis[i] = inf;
dis[s] = 0;
queue<int> q;
q.push(s);
while (!q.empty())
{
int u = q.front();
q.pop();
vis[u] = false;
for (int i = head2[u]; i; i = e2[i].next)
{
int v = e2[i].v, w = e2[i].w;
if (dis[v] > dis[u] + w)
{
dis[v] = dis[u] + w;
if (!vis[v])
{
vis[v] = true;
q.push(v);
}
}
}
}
}
void a_star(int s, int t)
{
if (s == t) k++;
priority_queue<anode> q;
q.push(anode{s, 0, 0});
int cnt = 0;
while (!q.empty())
{
anode a = q.top();
q.pop();
if (a.id == t && ++cnt == k)
{
printf("%d\n", a.f);
return;
}
for (int i = head1[a.id]; i; i = e1[i].next)
q.push(anode{e1[i].v, a.g + e1[i].w + dis[e1[i].v], a.g + e1[i].w});
}
printf("-1\n");
}
int main()
{
n = read(); m = read();
for (int i = 1, u, v, w; i <= m; i++)
{
u = read(); v = read(); w = read();
addedge(u, v, w);
}
s = read(); t = read(); k = read();
spfa(t);
a_star(s, t);
return 0;
}
// 树状数组
int lowbit(int x)
{
return x & -x;
}
void add(int p, int x)
{
for (int i = p; i <= n; i += lowbit(i))
tree[i] += x;
}
int getSum(int p)
{
int res = 0;
for (int i = p; i > 0; i -= lowbit(i))
res += tree[i];
return res;
}
// 线段树
struct node { int l, r; ll sum, lazy; } tree[maxn << 2];
inline int ls(int id) { return id << 1; }
inline int rs(int id) { return id << 1 | 1; }
void push_up(int id) { tree[id].sum = tree[ls(id)].sum + tree[rs(id)].sum; }
void push_down(int id)
{
if (tree[id].lazy)
{
tree[ls(id)].sum += (tree[ls(id)].r - tree[ls(id)].l + 1) * tree[id].lazy;
tree[rs(id)].sum += (tree[rs(id)].r - tree[rs(id)].l + 1) * tree[id].lazy;
tree[ls(id)].lazy += tree[id].lazy;
tree[rs(id)].lazy += tree[id].lazy;
tree[id].lazy = 0;
}
}
void build(int id, int l, int r)
{
if ((tree[id].l = l) == (tree[id].r = r))
{
scanf("%lld", &tree[id].sum);
return;
}
int mid = (l + r) >> 1;
build(ls(id), l, mid);
build(rs(id), mid + 1, r);
push_up(id);
}
void update(int id, int l, int r, ll v)
{
if (tree[id].l == l && tree[id].r == r)
{
tree[id].sum += (r - l + 1) * v;
tree[id].lazy += v;
return;
}
push_down(id);
int mid = (tree[id].l + tree[id].r) >> 1;
if (r <= mid) update(ls(id), l, r, v);
else if (l > mid) update(rs(id), l, r, v);
else
{
update(ls(id), l, mid, v);
update(rs(id), mid + 1, r, v);
}
push_up(id);
}
ll query(int id, int l, int r)
{
if (tree[id].l == l && tree[id].r == r) return tree[id].sum;
push_down(id);
int mid = (tree[id].l + tree[id].r) >> 1;
if (r <= mid) return query(ls(id), l, r);
if (l > mid) return query(rs(id), l, r);
return query(ls(id), l, mid) + query(rs(id), mid + 1, r);
}
// 线段树区间合并
// POJ3667 Hotel
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 5e4 + 10;
struct node { int l, r, sum, lsum, rsum, lz; } tree[maxn << 2];
// sum: 该节点区间内状态全部为0的最大子区间长度
inline const int read()
{
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + ch - '0'; ch = getchar(); }
return x * f;
}
inline int ls(int id) { return id << 1; }
inline int rs(int id) { return id << 1 | 1; }
void build(int id, int l, int r)
{
tree[id].lz = -1;
tree[id].l = l;
tree[id].r = r;
tree[id].sum = tree[id].lsum = tree[id].rsum = r - l + 1;
if (l == r) return;
int mid = (l + r) >> 1;
build(ls(id), l, mid);
build(rs(id), mid + 1, r);
}
void push_up(int id)
{
tree[id].lsum = tree[ls(id)].lsum;
tree[id].rsum = tree[rs(id)].rsum;
if (tree[ls(id)].sum == tree[ls(id)].r - tree[ls(id)].l + 1) tree[id].lsum += tree[rs(id)].lsum;
if (tree[rs(id)].sum == tree[rs(id)].r - tree[rs(id)].l + 1) tree[id].rsum += tree[ls(id)].rsum;
tree[id].sum = max(max(tree[ls(id)].sum, tree[rs(id)].sum), tree[ls(id)].rsum + tree[rs(id)].lsum);
}
void push_down(int id)
{
if (tree[id].lz != -1)
{
tree[ls(id)].lz = tree[rs(id)].lz = tree[id].lz;
tree[ls(id)].sum = tree[ls(id)].lsum = tree[ls(id)].rsum = tree[id].lz ? 0 : tree[ls(id)].r - tree[ls(id)].l + 1;
tree[rs(id)].sum = tree[rs(id)].lsum = tree[rs(id)].rsum = tree[id].lz ? 0 : tree[rs(id)].r - tree[rs(id)].l + 1;
tree[id].lz = -1;
}
}
void update(int id, int l, int r, bool x)
{
if (tree[id].l == l && tree[id].r == r)
{
tree[id].lz = x;
tree[id].sum = tree[id].lsum = tree[id].rsum = x ? 0 : tree[id].r - tree[id].l + 1;
return;
}
push_down(id);
int mid = (tree[id].l + tree[id].r) >> 1;
if (r <= mid) update(ls(id), l, r, x);
else if (l > mid) update(rs(id), l, r, x);
else
{
update(ls(id), l, mid, x);
update(rs(id), mid + 1, r, x);
}
push_up(id);
}
// 查询l, r区间内第一个状态全部为0且长度达到x的子区间左边界
int query(int id, int l, int r, int x)
{
if (l == r) return l;
push_down(id);
int mid = (tree[id].l + tree[id].r) >> 1;
if (tree[ls(id)].sum >= x) return query(ls(id), l, mid, x);
if (tree[ls(id)].rsum + tree[rs(id)].lsum >= x) return mid - tree[ls(id)].rsum + 1;
return query(rs(id), mid + 1, r, x);
}
int main()
{
int n = read(), m = read();
build(1, 1, n);
while (m--)
{
int ope = read(), k, a, b;
switch (ope)
{
case 1:
k = read();
if (tree[1].sum < k) printf("0\n");
else
{
printf("%d\n", a = query(1, 1, n, k));
update(1, a, a + k - 1, true);
}
break;
case 2:
a = read(); b = read();
update(1, a, a + b - 1, false);
}
}
return 0;
}
// HDOJ1540 Tunnel Warfare
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e4 + 10;
struct node { int l, r, sum, lsum, rsum; } tree[maxn << 2];
// sum: 当前节点区间内最大连通子区间长度
inline const int read()
{
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + ch - '0'; ch = getchar(); }
return x * f;
}
inline int ls(int id) { return id << 1; }
inline int rs(int id) { return id << 1 | 1; }
void build(int id, int l, int r)
{
tree[id].l = l;
tree[id].r = r;
tree[id].lsum = tree[id].rsum = tree[id].sum = r - l + 1;
if (l == r) return;
int mid = (l + r) >> 1;
build(ls(id), l, mid);
build(rs(id), mid + 1, r);
}
void push_up(int id)
{
tree[id].lsum = tree[ls(id)].lsum;
tree[id].rsum = tree[rs(id)].rsum;
if ((tree[ls(id)].sum) == tree[ls(id)].r - tree[ls(id)].l + 1) tree[id].lsum += tree[rs(id)].lsum;
if ((tree[rs(id)].sum) == tree[rs(id)].r - tree[rs(id)].l + 1) tree[id].rsum += tree[ls(id)].rsum;
tree[id].sum = max(max(tree[ls(id)].sum, tree[rs(id)].sum), tree[ls(id)].rsum + tree[rs(id)].lsum);
}
void update(int id, int tar, bool x)
{
if (tree[id].l == tar && tree[id].r == tar)
{
tree[id].lsum = tree[id].rsum = tree[id].sum = x;
return;
}
int mid = (tree[id].l + tree[id].r) >> 1;
if (tar <= mid) update(ls(id), tar, x);
else update(rs(id), tar, x);
push_up(id);
}
// 查询在当前节点区间内包含目标节点的最大连通子区间长度
int query(int id, int tar)
{
if (tree[id].l == tree[id].r || tree[id].sum == tree[id].r - tree[id].l + 1 || tree[id].sum == 0) return tree[id].sum;
int mid = (tree[id].l + tree[id].r) >> 1;
if (tar <= mid) return tar >= tree[ls(id)].r - tree[ls(id)].rsum + 1 ? query(ls(id), tar) + query(rs(id), mid + 1) : query(ls(id), tar);
return tar <= tree[rs(id)].l + tree[rs(id)].lsum - 1 ? query(rs(id), tar) + query(ls(id), mid) : query(rs(id), tar);
}
int main()
{
int n, m, cnt, des[maxn];
while (~scanf("%d%d", &n, &m))
{
cnt = 0;
build(1, 1, n);
while (m--)
{
char ope[2]; int x;
scanf("%s", ope);
switch (ope[0])
{
case 'D':
scanf("%d", &x);
des[cnt++] = x;
update(1, x, 0);
break;
case 'Q':
scanf("%d", &x);
printf("%d\n", query(1, x));
break;
case 'R':
update(1, des[--cnt], 1);
}
}
}
return 0;
}
// 扫描线
// The Preliminary Contest for ICPC Asia Nanjing 2019 A. The beautiful values of the palace
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
const int maxm = 1e5 + 10;
int t, n, m, p, cnt, ans[maxm];
struct node { int l, r, sum; } tree[maxn << 2];
struct cor { int x, y, type, qid; } cord[maxm << 2];
struct qes { int x1, x2; } qest[maxm];
// type == 0: square for update, type == 1: lower left square for query, type == 2: upper right square for query
inline const int read()
{
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + ch - '0'; ch = getchar(); }
return x * f;
}
int getVal(ll x, ll y)
{
x = x - n / 2 - 1;
y = y - n / 2 - 1;
ll tmp = max(abs(x), abs(y));
ll num = x >= y ? (ll)n * n - tmp * tmp * 4 - tmp * 2 - x - y : (ll)n * n - tmp * tmp * 4 + tmp * 2 + x + y;
int res = 0;
do { res += num % 10; num /= 10; } while (num);
return res;
}
bool cmp(const cor& a, const cor& b)
{
if (a.y != b.y) return a.y < b.y;
if (a.x != b.x) return a.x < b.x;
if ((a.type == 0 && b.type == 1) || (a.type == 1 && b.type == 0)) return a.type > b.type;
return a.type < b.type;
}
inline int ls(int id) {return id << 1;}
inline int rs(int id) {return id << 1 | 1;}
void push_up(int id)
{
tree[id].sum = tree[ls(id)].sum + tree[rs(id)].sum;
}
void build(int id, int l, int r)
{
tree[id].l = l; tree[id].r = r; tree[id].sum = 0;
if (l == r) return;
int mid = (l + r) >> 1;
build(ls(id), l, mid);
build(rs(id), mid + 1, r);
push_up(id);
}
void update(int id, int l, int r, int v)
{
if (tree[id].l == l && tree[id].r == r)
{
tree[id].sum += (r - l + 1) * v;
return;
}
int mid = (tree[id].l + tree[id].r) >> 1;
if (r <= mid) update(ls(id), l, r, v);
else if (l > mid) update(rs(id), l, r, v);
else
{
update(ls(id), l, mid, v);
update(rs(id), mid + 1, r, v);
}
push_up(id);
}
int query(int id, int l, int r)
{
if (tree[id].l == l && tree[id].r == r) return tree[id].sum;
int mid = (tree[id].l + tree[id].r) >> 1;
if (r <= mid) return query(ls(id), l, r);
if (l > mid) return query(rs(id), l, r);
return query(ls(id), l, mid) + query(rs(id), mid + 1, r);
}
int main()
{
t = read();
while (t--)
{
cnt = 0;
n = read(); m = read(); p = read();
build(1, 1, n);
for (int i = 0; i < m; i++)
{
int x = read(), y = read();
cord[cnt++] = cor{x, y, 0, 0};
}
for (int i = 0; i < p; i++)
{
int x1 = read(), y1 = read(), x2 = read(), y2 = read();
cord[cnt++] = cor{x1, y1, 1, i};
cord[cnt++] = cor{x2, y2, 2, i};
qest[i] = qes{x1, x2};
}
sort(cord, cord + cnt, cmp);
for (int i = 0; i < cnt; i++)
{
int x = cord[i].x, y = cord[i].y, id = cord[i].qid;
if (cord[i].type == 0) update(1, x, x, getVal(x, y));
else if (cord[i].type == 1) ans[id] = query(1, qest[id].x1, qest[id].x2);
else ans[id] = query(1, qest[id].x1, qest[id].x2) - ans[id];
}
for (int i = 0; i < p; i++) printf("%d\n", ans[i]);
}
return 0;
}