普及组
T1文具采购
Description
给定整数 $n$ ,求出 $a,b,c$ 满足以下性质
- $7a+4b+3c = n$
- $MAX\ (min (a,b,c))$
- $MAX(a+b+c)$
Solution
针对性质 $2$,我们令 $k =MAX\ (min (a,b,c))$,那么易得 $k$ 在 $\frac{n}{7+4+3}$ 附近
然后,由数论知识可知,对于质数 $p,q$ ,用 $X=ap+bq(a,b\ge 0)$,不能组成的最大的 $X=(p-1)*(q-1)-1$
对于本题,发现不能组成的数字为 $1 , 2 ,5.(3,4来组数)$
然后我们很容易想到当$x = 15$ 时候,虽然 $x\equiv 1\pmod {14}$,但他其实有解,不难想到这个边间为 $19$(因为当剩下的数字$\ge20$ 时候,条件 2 不符合了。)
预处理一下就行了。
Code
1 | // She is Pretty pretty! |
Description
Solution
Code
魔法
Description
中文题面略略略
挂两个similar的题
Codeforces Round #319 (Div. 1)-D. Flights for Regular Customers
poj3613 牛站
Solution
法一:倍增 $Floyd$
法二:广义矩阵快速幂优化 $dp$
本文采用法二我是不会说我没做过倍增Floyd的
不妨令$dp{k,i,j}$ 表示从 $i$ 到 $j$ ,使用魔法次数不超过 $k$ 次的所有方案钟的最短路。
容易得到转移方程为: $$dp{k,i,j} = min(dp{k-1,i,t}+dp{1,t,j})$$
由广义矩阵乘法具有结合率(不知道这样描述对不对。)但在离散中是有这样一个结论的:
对于一个邻接矩阵 $G$ ,那么 $G^k$ 表示的就是恰好经过 $k$ 次后的状态。
这为矩阵快速幂优化提供理论基础。
考虑子问题,
当 $k=0$ 时,$floyd$ 解决即可。
当 $k=1$ 时, 即用一次魔法,枚举每一条边 $(u,v,w)$, $dp{1,i,j}=dp{0,i,u}-w+dp_{0,v,j}$ 时间复杂度 $O(n^2m)$
总时间复杂度为 $O(n^3logK+n^2m)$
Code
写矩阵一定要注意初始化的问题!!!!
矩阵不规范,debug两行泪
注意,后来的a矩阵就是用了一次魔法的矩阵1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94// She is Pretty pretty!
using namespace std;
const int N = 1e6 + 100;
const int MAXN = 110;
const int MAXM = 2505;
int n, m, k, u, v, w, dis[MAXN][MAXN];
std::tuple<int, int, int> e[MAXM];
struct Matrix {
int a[MAXN][MAXN];
Matrix() {}
Matrix(int tmp[MAXN][MAXN]) {
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) a[i][j] = tmp[i][j];
}
Matrix operator*(Matrix const &b) {
int tmp[MAXN][MAXN];
memset(tmp, 0x3f, sizeof tmp);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
for (int k = 1; k <= n; k++) {
tmp[i][j] = min(tmp[i][j], a[i][k] + b.a[k][j]);
}
}
}
return Matrix(tmp);
}
friend Matrix operator^(Matrix base, int n) {
Matrix res = base;
n--;
for (; n; n >>= 1, base = base * base) {
if (n & 1) {
res = res * base;
}
}
return res;
}
/*Matrix Qpow(ll p) //矩阵快速幂,求a^p
{
--p;
Matrix res = *this, cur = *this;
while (p) {
if (p & 1) res = res * cur;
cur = cur * cur;
p >>= 1;
}
return res;
}*/
} a;
void floyd(int n) {
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
}
int32_t main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m >> k;
memset(dis, 0x3f, sizeof dis);
for (int i = 1; i <= n; i++) dis[i][i] = 0;
for (int i = 1; i <= m; i++) {
cin >> u >> v >> w;
e[i] = {u, v, w};
dis[u][v] = min(dis[u][v], w);
}
floyd(n);
a = Matrix(dis);
if (k == 0) {
return cout << dis[1][n], 0;
}
for (int i = 1; i <= m; i++) {
auto [u, v, w] = e[i];
for (int s = 1; s <= n; s++) {
for (int t = 1; t <= n; t++) {
a.a[s][t] = min(a.a[s][t], dis[s][u] + dis[v][t] - w);
}
}
}
Matrix ans = Matrix((a ^ k).a);
cout << ans.a[1][n];
// cout << a.Qpow(k).a[1][n];
return 0;
}