前言
打GYM时遇见了一题同余最短路,队友写过,今天来补下知识点
P3403 跳楼机
题目链接:跳楼机
大意:给定
x
,
y
,
z
x,y,z
x,y,z,求能组合成多少个小于h的数。
数据范围:
1
≤
x
,
y
,
z
≤
1
e
5
1\le x,y,z\le1e5
1≤x,y,z≤1e5
题解:同余最短路
AC代码:
#include<bits/stdc++.h>
#define int long long
#define ld long double
#define ll long long
using namespace std;
template<class T>
void read(T& x)
{
T res = 0, f = 1; char c = getchar();
while (!isdigit(c)) {
if (c == '-')f = -1; c = getchar();
}
while (isdigit(c)) {
res = (res << 3) + (res << 1) + c - '0'; c = getchar();
}
x = res * f;
}
const ll N = 200000 + 10;
const int mod = 1e9 + 7;
int a[5],h,dis[N];
bool in[N];
signed main()
{
//ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("test.in", "r", stdin);
#endif // ONLINE_JUDGE
read(h); h--;
for (int i = 1; i <= 3; i++)read(a[i]);
sort(a + 1, a + 1 + 3);
memset(dis, 0x3f, sizeof(dis));
queue<int>pls;
pls.push(0); dis[0] = 0; in[0] = 1;
while (pls.size())
{
int f = pls.front(); pls.pop(); in[f] = 0;
for (int i = 2; i <= 3; i++)
{
int t = (f + a[i]) % a[1];
if (dis[t] > dis[f] + a[i])
{
dis[t] = dis[f] + a[i];
if (!in[t])pls.push(t), in[t] = 1;
}
}
}
ll ans = 0;
for (int i = 0; i < a[1]; i++)
{
if (h < dis[i])continue;
ans += (h - dis[i]) / a[1] + 1;
}
printf("%lld\n", ans);
return 0;
}
GYM100753 M-Sums
题目链接:M-Sums
题目大意:给定n个数
a
1
−
n
a_{1-n}
a1−n。
q
q
q次询问,询问
a
a
a数组是否能组合成
k
k
k。
数据范围:
1
≤
a
i
≤
50000
,
1
≤
n
≤
50000
,
k
≤
1
e
18
,
q
≤
100000
1\le a_i\le 50000,1\le n\le 50000,k\le 1e18,q\le 100000
1≤ai≤50000,1≤n≤50000,k≤1e18,q≤100000
题解:同余最短路
AC代码:
#include<bits/stdc++.h>
#define ld long double
#define ll long long
using namespace std;
template<class T>
void read(T& x)
{
T res = 0, f = 1; char c = getchar();
while (!isdigit(c)) {
if (c == '-')f = -1; c = getchar();
}
while (isdigit(c)) {
res = (res << 3) + (res << 1) + c - '0'; c = getchar();
}
x = res * f;
}
const ll N = 200000 + 10;
const int mod = 1e9 + 7;
int a[N], dis[N],n,vis[N];
int main()
{
//ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("test.in", "r", stdin);
#endif // ONLINE_JUDGE
read(n);
for (int i = 1; i <= n; i++)read(a[i]);
sort(a + 1, a + 1 + n);
memset(dis, 0x3f, sizeof(dis));
dis[0] = 0;
queue<int>pls;
pls.push(0); vis[0] = 1;
while (pls.size())
{
int f = pls.front(); pls.pop(); vis[f] = 0;
for (int i = 1; i <= n; i++)
{
int to = (f + a[i]) % a[1];
if (dis[to] > dis[f] + a[i])
{
dis[to] = dis[f] + a[i];
if (!vis[to])
pls.push(to), vis[to] = 1;
}
}
}
int q; read(q);
while (q--)
{
int x; read(x);
printf("%s\n", x >= dis[x % a[1]] ? "TAK" : "NIE");
}
return 0;
}
P2371 [国家集训队]墨墨的等式
题目链接:P2371 [国家集训队]墨墨的等式
大意:
数据范围:
1
≤
n
≤
12
,
0
≤
a
i
≤
5
∗
1
0
5
,
1
≤
l
,
r
≤
1
e
12
1\le n\le 12,0\le a_i\le5*10^5,1\le l,r\le 1e12
1≤n≤12,0≤ai≤5∗105,1≤l,r≤1e12
题解:同余最短路。
AC代码:
#include<bits/stdc++.h>
#define int long long
#define ld long double
#define ll long long
using namespace std;
template<class T>
void read(T& x)
{
T res = 0, f = 1; char c = getchar();
while (!isdigit(c)) {
if (c == '-')f = -1; c = getchar();
}
while (isdigit(c)) {
res = (res << 3) + (res << 1) + c - '0'; c = getchar();
}
x = res * f;
}
const ll N = 500000 + 10;
const int mod = 1e9 + 7;
int a[20],n,l,r,dis[N];
bool in[N];
ll query(int x)
{
ll ans = 0;
for (int i = 0; i < a[1]; i++)
{
if (x < dis[i])continue;
ans += (x - dis[i]) / a[1] + 1;
}
return ans;
}
signed main()
{
//ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("test.in", "r", stdin);
#endif // ONLINE_JUDGE
read(n), read(l), read(r);
for (int i = 1; i <= n; i++)read(a[i]);
sort(a + 1, a + 1 + n);
memset(dis, 0x3f, sizeof(dis));
queue<int>pls;
pls.push(0); dis[0] = 0; in[0] = 1;
while (pls.size())
{
int f = pls.front(); pls.pop(); in[f] = 0;
for (int i = 2; i <= n; i++)
{
int t = (f + a[i]) % a[1];
if (dis[t] > dis[f] + a[i])
{
dis[t] = dis[f] + a[i];
if (!in[t])pls.push(t), in[t] = 1;
}
}
}
printf("%lld\n", query(r)-query(l-1));
return 0;
}