[LuoguP2371]墨墨的等式
题面:Luogu
题解:最短路
本来想放张图上来,结果发现\(n=2\)数据太小没用,\(n=3\)到处都是重边,就不放图了
首先我们可以求出\(b\le r\)的数量和\(b\le l-1\)的数量,然后两个相减就是答案
考虑怎么求出符合条件的
设
\[minnum=\min_{1\le i\le n}a[i] \\
\sum_{i=1}^{n}{a[i]*x[i]}=k \rightarrow\sum_{i=1}^{n}{a[i]*x[i]}=k+x*minnum
\]
为什么取最小值?因为这样符合条件的数最多而且跑的最快,因为连边最少
设\(dis[i]\)表示\(b\equiv i~(mod~minnum)\)的最小值
于是连有向边\((i,(i+a[j])\%minnum,a[j])\)表示本来余数为\(i\),加上\(a[j]\)后余数改变
然后跑以\(0\)为源点跑最短路(spfa即可,这道题连边方式决定了它卡不了spfa)(当然我还是用的dijskra)
然后如果要求\([0,x]\)间的数量,如果\(dis[i]\le x\)则
\[ans+=\lfloor \frac{x-dis[i]}{minnum} \rfloor+1
\]
还是给一组小数据吧
4 5 20
5 6 12 13
\(dis\)值是\(0,6,12,13,19\)(注意是从\(0\)开始编号的)
主要是连边和\(dis\)的意义可以感性理解一下,其它的应该没什么
注意开\(long~long\),以及\(inf\)要开大一点
#include<bits/stdc++.h>
using namespace std;
template<typename T>
inline void read(T& x)
{
x = 0; char c = getchar();
while (!isdigit(c)) c = getchar();
while (isdigit(c)) x = x * 10 + c - '0', c = getchar();
}
#define maxn 500005
#define ll long long
struct Edge
{
int fr, to, val;
}eg[maxn * 20];
int head[maxn], edgenum;
inline void add(int fr, int to, int val)
{
eg[++edgenum] = { head[fr],to,val };
head[fr] = edgenum;
}
#define pa pair<int,int>
#define mp make_pair
priority_queue<pa, vector<pa>, greater<pa> >q;
int vis[maxn], minnum;
ll l, r, dis[maxn];
void dijskra(int s)
{
for (int i = 0; i < minnum; ++i) dis[i] = 1e18;
dis[s] = 0; q.push(mp(dis[s], s));
while (!q.empty())
{
int tp = q.top().second; q.pop();
if (vis[tp]) continue; vis[tp] = 1;
for (int i = head[tp]; i; i = eg[i].fr)
if (dis[eg[i].to] > dis[tp] + eg[i].val)
dis[eg[i].to] = dis[tp] + eg[i].val, q.push(mp(dis[eg[i].to], eg[i].to));
}
}
inline ll query(ll x)
{
ll ans = 0;
for (int i = 0; i < minnum; ++i)
if (dis[i] <= x) ans += (x - dis[i]) / minnum + 1;
return ans;
}
int a[maxn], n, m;
int main()
{
read(n), read(l), read(r);
minnum = 0x3f3f3f3f;
for (int i = 1, tp; i <= n; ++i)
{
read(tp);
if (tp) a[++m] = tp, minnum = min(minnum, tp);
}
n = m;
for (int i = 0; i < minnum; ++i)
for (int j = 1; j <= n; ++j)
if(a[j] != minnum) add(i, (i + a[j]) % minnum, a[j]);
dijskra(0);
printf("%lld\n", query(r) - query(l - 1));
return 0;
}
一切伟大的行动和思想,都有一个微不足道的开始。
There is a negligible beginning in all great action and thought.
There is a negligible beginning in all great action and thought.