思路:
设最小a为min
发现如果
a
1
∗
i
1
+
a
2
∗
i
2
+
…
…
+
a
n
∗
i
n
a_1*i_1+a_2*i_2+……+a_n*i_n
a1∗i1+a2∗i2+……+an∗in能达到
k
∗
m
i
n
+
t
k*min+t
k∗min+t,那么后面这个加上多少个min,它都是能达到的。
所以spfa出到达t这个余数的最小和是多少,然后直接
(
r
−
d
i
s
)
/
m
i
n
(r-dis)/min
(r−dis)/min得出最多可以加几次
c o d e code code
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define ll long long
using namespace std;
const ll mod = 1e9 + 7;
ll n, l, r, minn = 1e9;
ll a[100], dis[1000010];
bool v[1000010];
void spfa(ll s) {
queue<ll> q;
q.push(s);
memset(dis, 0x7f, sizeof(dis));
dis[s] = 0;
v[s] = 1;
while(!q.empty()) {
ll x = q.front();
q.pop();
for(ll i = 1; i <= n; i ++) {
ll y = (x + a[i]) % minn;
if(dis[y] > dis[x] + a[i]) {
dis[y] = dis[x] + a[i];
if(!v[y]) {
q.push(y);
v[y] = 1;
}
}
}
v[x] = 0;
}
}
ll query_(ll x) {
ll ans = 0;
for(ll i = 0; i < minn; i ++)
if(x >= dis[i]) ans = (ans + (x - dis[i]) / minn + 1) % mod;
return ans;
}
int main() {
scanf("%lld%lld%lld", &n, &l, &r);
for(ll i = 1; i <= n; i ++) scanf("%lld", &a[i]), minn = min(a[i], minn);
spfa(0);
printf("%lld", (query_(r) - query_(l - 1) + mod) % mod);
return 0;
}