1.
模拟+剪枝
#include<cstdio> #include<iostream> using namespace std; int main() { int n; int a,b,c; scanf("%d",&n); a=n/14; b=n/14; c=n/14; if (n==1||n==2||n==5) { printf("-1"); return 0; } else if (n%14==1) { c--; b=b+2; } else if (n%14==2) { a=a+3; c--; } else if (n%14==3) { a++; } else if (n%14==4) { b++; } else if (n%14==5) { c--; a=a+4; } else if (n%14==6) { a=a+2; } else if (n%14==7) { a++; b++; } else if (n%14==8) { b=b+2; } else if (n%14==9) { a=a+3; } else if (n%14==10) { a=a+2; b=b+1; } else if (n%14==11) { a=a+1; b=b+2; } else if (n%14==12) { a=a+4; } else if (n%14==13) { a=a+3; b=b+1; } printf("%d %d %d",c,b,a); return 0; }
2.
其实就是分拆数问题。分拆数问题本质上是 n 也无标号的第二类斯特林数问题(第二类斯特林数是 n 有标号但是 k 无标号)。
那么对于这个问题,考虑两种 dp.
- 1、令 f_{i,j}fi,j 表示对于 i 拆分成若干个不大于 j 的数的方案数。则有转移:
f_{i,j}=f{i,j-1}+f{i-j,j}
后面一项 f_{i-j,j}fi−j,j 可以看成一个背包一样,后面的状态对前面的状态有天然的累加效应,所以只需要考虑丢掉一个 jj 的情况;而前面一项则把我们转移从后一项的等于 jj 升级成为不大于 jj 。
- 2、令 g{i,j} 表示对于 ii 拆分成 jj 个数的方案数。则有转移:
g_{i,j}=g_{i-1,j-1}+g_{i-j,j}gi,j=gi−1,j−1+gi−j,j
#include <bits/stdc++.h> #define LL long long using namespace std; const int N = 100005; int f[N]; int g[400][N]; int main() { int n, p; cin >> n >> p; int m = sqrt(n) + 1; f[0] = 1; for (int i = 1; i < m; i++) { for (int j = i; j <= n; j++) { f[j] += f[j - i]; f[j] %= p; } } g[0][0] = 1; for (int i = 1; i < m; i++) { for (int j = i; j <= n; j++) { g[i][j] = g[i][j - i]; if (j >= m) g[i][j] += g[i - 1][j - m]; g[i][j] %= p; } } int ans = 0; for (int i = 0; i <= n; i++) { LL sum = 0; for (int j = 0; j < m; j++) sum += g[j][n - i]; sum %= p; ans = (ans + f[i] * sum) % p; } cout << ans << endl; return 0; }
3.
矩阵快速幂优化DP(还没写完回来补)
#include <bits/stdc++.h> using namespace std; typedef long long LL; const LL INF = 0x3f3f3f3f3f3f3f3f; const int N = 100; typedef LL Matrix[N][N]; int sz; LL a[N][N]; void matrix_mul(Matrix A, Matrix B, Matrix res) { Matrix C; for (int i = 0; i < sz; i++) { for (int j = 0; j < sz; j++) { C[i][j] = INF; for (int k = 0; k < sz; k++) { C[i][j] = min(C[i][j], A[i][k] + B[k][j]); } } } for (int i = 0; i < sz; i++) { for (int j = 0; j < sz; j++) { res[i][j] = C[i][j]; } } } void matrix_pow(Matrix A, LL p, Matrix res) { Matrix x; for (int i = 0; i < sz; i++) { for (int j = 0; j < sz; j++) { x[i][j] = A[i][j]; res[i][j] = a[i][j]; } } while (p) { if (p & 1) matrix_mul(res, x, res); p >>= 1; matrix_mul(x, x, x); } } struct Edge { int u, v, w; } b[2505]; int main() { int n, m, K; scanf("%d%d%d", &n, &m, &K); sz = n; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) a[i][j] = i == j ? 0 : INF; for (int i = 0; i < m; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); u--; v--; b[i] = {u, v, w}; a[u][v] = min(a[u][v], (LL)w); } for (int k = 0; k < n; k++) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { a[i][j] = min(a[i][j], a[i][k] + a[k][j]); } } } Matrix c; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { c[i][j] = a[i][j]; for (int k = 0; k < m; k++) { c[i][j] = min(c[i][j], a[i][b[k].u] - b[k].w + a[b[k].v][j]); } } } matrix_pow(c, K, c); printf("%lld\n", c[0][n - 1]); return 0; }