标签:scan push for ios sig signed define while phi
考虑贪心,显然在价格低的地方要多买电,使电量达到上限或者能到达更便宜的充电站
所以得到一个暴力的想法,对于每一个电站,求出凭借它的电能到达的电站,如果能到更便宜的电站,那么就充能够到达最便宜电站的电,否则在其它比较便宜的电站补电。
然后发现可以考虑反悔,在每一个充电站把电充满,遇到更便宜的充电站时把已经充了的还没有用掉的比当前更贵的电反悔掉。
发现单调队列可以很好的进行这个操作。
步骤:
#include <iostream>
#include <cstdio>
#include <queue>
#include <functional>
#include <deque>
#define int long long
using namespace std;
const int N = 1e6 + 10;
int n, t;
int d[N], p[N];
deque<pair<int, int> > q;
signed main()
{
scanf("%lld%lld", &n, &t);
int cnt = t;
int ans = 0;
for (int i = 1; i <= n; ++i)
{
scanf("%lld%lld", &d[i], &p[i]);
if (d[i] > t)
{
puts("-1");
return 0;
}
while (q.size() && q.back().first > p[i])
{
ans -= q.back().first * q.back().second;
cnt += q.back().second;
q.pop_back();
}
q.push_back(make_pair(p[i], cnt));
ans += p[i] * cnt;
cnt = d[i];
while (q.size() && q.front().second <= d[i])
{
d[i] -= q.front().second;
q.pop_front();
}
if (q.size() && d[i])
{
q.front().second -= d[i];
}
}
while (q.size())
{
ans -= q.front().first * q.front().second;
q.pop_front();
}
cout << ans <<endl;
return 0;
}
数位 \(dp\) 裸题
二项式反演裸题
设 \(g(k)\) 表示钦定至少全部都会 \(k\) 种算法的方案数。
即 \(g(k) = \tbinom{n}{k}(2^{(2^{n-k})}-1)\) 因为在钦定 \(k\) 种算法后,其它算法随意,所以有 \(2^{n-k}\) 种算法组合,每种算法组合都随意存在,所以共有 \(2^{(2^{n-k})}\) 种算法组合的组合,注意算法组合的组合不能为空,所以要 \(-1\)
然后设 \(f(k)\) 表示所有同学全部都会的算法恰好为 \(k\) 种的方案数。
有式子:\(g(k) = \sum_{i=k}^{n}\tbinom{i}{k}f(i)\)
因为对于每种方案,其中都有 \(k\) 种算法可能是被钦定的。
然后只需要二项式反演得到 : \(f(k) = \sum_{i=k}^{n} (-1)^{i-k} \tbinom{i}{k} g(i)\)
要注意 \(2^{(2^{n-k})}\) 中指数要模的是 \(\varphi(p)\)
显然 \(a\) 和 \(b\) 一定是在最短路上的点,所以先把所有在最短路上的点求出来。
从 \(1\) 求最短路 \(f_i\), 再从 \(n\) 求最短路\(g_i\),对于每个点 \(i\) 如果 \(f_i + g_i = f_n\) 那么这个点为最短路上的点。
因为先到 \(a\), 再到 \(b\) 所有对于最短路上的点建一个 \(dag\) :对于有边相连的点对,由 \(f_i\) 小的点向 \(f_i\) 大的点连边。
对于每个最短路上的点,如果它是 \(b\) ,那么 \(a\) 就是它的前驱,每个点的前驱就是它直接前驱的前驱并,用 \(bitset\) 维护。
复杂度 \(O((n+m)\lg n + \frac{(n+m)n}{32})\) ,时间给开了 \(2\) 秒,应该不会被卡常
标签:scan push for ios sig signed define while phi
原文地址:https://www.cnblogs.com/youwike/p/14964313.html