题目目录
- 队列
- 多项式求值
- 买菜
队列
题意
有 $n$ 名学生参加军训,军训的一大重要内容就是走队列,而一个队列的不整齐程度是该队中最高的学生的身高与最矮的学生的身高差值的平方。
现在要将 $n$ 名参加军训的学生分成 $k$ 个队列,每个队列的人数可以是任意非负整数。在安排队列时希望所有队列的不整齐度之和尽量小,请问不整齐度之和最小可以是多少?
对于所有的数据,$1\leq n,k\leq 500,0\leq \text{学生身高}\leq 200$。
题解
动态规划。我们将高度排序,然后把划分队列转化为插板,考虑 $dp[i][j]$ 表示用了 $i$ 块板,最后一块板插在 $j$ 的位置,然后我们就有了一个 $\mathcal O(kn^2)$的做法。
考虑两个相同身高的人,他们一定可以放在同一个队列中而不会增加代价。
于是,我们去重,然后我们判断 $k\geq n$ 的情况,只要输出 $0$ 就可以了。
这样,$n$ 一定 $\le k$,这样我们就有了一个 $\mathcal O(k^3)$ 的做法。
调试记录
- 初始化里面一个 $n$ 打成了 $k$。
代码
#include <bits/stdc++.h> #define down(x, y) x = min(x, y) using namespace std; #define int long long int a[505], f[505][505]; signed main() { // freopen("queue.in", "r", stdin); // freopen("queue.out", "w", stdout); int n, k; scanf("%lld%lld", &n,&k); for (int i=1; i<=n; i++) scanf("%lld", &a[i]); sort(a+1, a+1+n); n = unique(a+1, a+1+n) - (a+1); if (n <= k) { puts("0"); return 0; } memset(f, 0x3f, sizeof(f)); f[0][0] = 0; for (int i=1; i<=n; i++) f[1][i] = (a[i]-a[1]) * (a[i]-a[1]); for (int i=2; i<k; i++) for (int j=1; j<=n; j++) for (int l=0; l<i; l++) { down(f[i][j], f[i-1][l] + (a[j]-a[l+1]) * (a[j]-a[l+1])); } int ans=1e9; for (int j=0; j<n; j++) ans = min(ans, f[k-1][j] + (a[n]-a[j+1])*(a[n]-a[j+1])); ans = min(ans, f[k-1][n]); printf("%lld\n", ans); return 0; }
多项式求值
题意
现在有一个多项式$f(x)=\sum_{i=0}^{m}b_ix^i$,对于给定的正整数 $a$,求$S(n)=\sum_{k=0}^{n}a^kf(k)$ 。
输出答案 $\bmod 10^9+7$ 。
对于 $100\%$ 的数据,$n\leq 10^9,m\leq 100$。
题解
请移步 `soj`。(注:`soj` 上面的题解是错的)
调试记录
- 忘记取模了 233
代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll P = 1000000007; ll PowerMod(ll x, ll y, ll p) { if (y == 0) return 1; if (y == 1) return x % p; if (y & 1) return PowerMod(x, y-1, p) * x % p; ll A = PowerMod(x, y>>1, p); return A * A % p; } struct Int { ll x; Int() : x(0) {} Int(ll y) : x(y % P) {} Int operator+(const Int & res) const { return (x + res.x) % P; } Int operator-(const Int & res) const { return (x - res.x + P) % P; } Int operator*(const Int & res) const { return x * res.x % P; } Int operator^(const Int & res) const { return (Int)PowerMod(x, res.x, P); } Int operator/(const Int & res) const { return x * (res ^ (P-2)).x % P; } friend Int operator+(ll x, const Int& y) { return (x%P + y.x) % P; } friend Int operator-(ll x, const Int& y) { return (x%P - y.x + P) % P; } friend Int operator*(ll x, const Int& y) { return x%P * y.x % P; } friend Int operator/(ll x, const Int& y) { return Int(x) / y; } friend Int operator^(ll x, const Int& y) { return Int(x) ^ y; } }; Int A[1005], b[1005], s[1005], SS[1005], frac[1005], n, m, a; Int S[1005][1005]; inline Int C(Int a, Int b) { if (a.x < b.x) return 0; if (a.x == b.x || b.x == 0) return 1; return frac[a.x] / frac[b.x] / frac[a.x - b.x]; } int main() { //freopen("poly.in", "r", stdin); //freopen("poly.out", "w", stdout); ll n,m,a; scanf("%lld%lld%lld", &n,&m,&a); :: n = n; :: m = m; :: a = a; for (int i=0; i<=m; i++) { ll x; scanf("%lld", &x); A[i] = x; } S[0][0] = 1; for (int i=1; i<=m; i++) { S[i][0] = 1; for (int j=1; j<=m; j++) S[i][j]=S[i-1][j]*(j+1)+S[i-1][j-1]; } frac[0] = 1; for (int i=1; i<=m; i++) frac[i] = frac[i-1] * i; Int ans; for (int i=0; i<=m; i++) { for (int j=0; j<=i; j++) { /*printf("S[%d][%d] is %lld\n", i,j,S[i][j].x); printf("val %lld\n", (A[i] * frac[j] * S[i][j]).x); if ((i+j)%2) printf("%d dec\n", i); else printf("%d add\n", i); printf("ori: %lld\n", b[i].x);*/ if ((i+j)%2) b[j] = b[j] - (A[i] * frac[j] * S[i][j]); else b[j] = b[j] + (A[i] * frac[j] * S[i][j]); //printf("after: %lld\n", b[i].x); } } SS[0] = 1; for (int i=0; i<=m; i++) SS[i+1] = SS[i]*(n+i+1)/(i+1); if (a == 1) { for (int i=0; i<=m; i++) s[i] = SS[i+1]; } else { Int an=::a^(n+1); s[0] = (1-an)/(1-::a); for (int i=1; i<=m; i++) s[i] = (s[i-1]-an*SS[i])/(1-::a); } for (int i=0; i<=m; i++) /*printf("s[%d] is %lld\n", i, s[i].x), */ans = ans + b[i] * s[i]; printf("%lld\n", ans.x); return 0; }