兩題切入 同餘最短路

2021-10-05 21:37:09 字數 2807 閱讀 8759

同餘最短路問題在acm比賽裡面考察的較少,屬於冷門的知識點,當我們遇到類似「給定n個整數,求這n個整數能組成多少種不同的數」等等問題的時候,可以考慮這種方法。

以p3403作為乙個簡單的示例:

有乙個高為h的大樓,每次可以向上移動x、y、z層,問可以到達的樓層數.

簡單的說,這道題就是讓求x*x1+y*x2+z*x3能組成多少個範圍在[1,h]內的數.

看到這道題的時候很容易想到無限揹包的方法,但是因為資料範圍巨大,所以不能使用揹包,於是就有人提出了使用同餘最短路的方法來解決這道題,使用同餘最短路並不是用同餘關係來執行最短路,而是我們找到一些狀態(通過同餘)來進行優化,通常這些狀態就是最短路中的點。

對於這道題,我們先把問題簡化為只有x和y兩個條件。

下面我直接說出解決的方法~~~~~~~~~

首先我們需要使用y來找到x的剩餘系.

假設i是num%x的餘數(num%x==i),那麼我們現在需要找到乙個最小的num,使得dist[i]=num.

對於y能湊出來的最小高度num,我們能找到(h-num)/x+1個符合條件的結果(加一是因為當前的num也要計算在內).

那麼我們只需要把所有的dist[i]加起來就就是最後的結果了。

現在我們分析這一道題

我們把y和z看作上面分析中的y,現在只需要用y和z組成dist[i]就行了,重新說一下dist[i]的意義:num%x==i的最小num就是dist[i],並且有下面兩個條件滿足:dist[i+y]=dist[i]+y,dist[i+z]=dist[i]+z.

在最短路差分約束的問題中就有類似的式子,現在我們可以直接通過上面的兩個式子建圖,然後跑最短路。

注:這裡的初始化與普通的最短路還不同,初始化dist[1]=1,因為最開始就在一樓。

#include#include#include#include#include#include#include#include#includeusing namespace std;

typedef long long ll;

const int maxn=2e5+100;

const int maxm=2e5+100;

const int inf=0x3f3f3f3f;

const ll inf=0x3f3f3f3f3f3f3f3f;

int head[maxm],l;

struct qnode

bool operator

};struct edge

};edge e[maxm];

bool vis[maxm];

ll dist[maxm];

void debug()

void init()

void dijkstra(int n,int start)}}

}void addedge(int u,int v,int w)

int main()

.讓我們計算有多少b可以使得我們的等式存在非負整數解(可以理解成不存在負數個數量的物品).

問題就是說對於a1,a2,.....an,能組成多少個範圍在[bmin,bmax]內的數.

剛看到這道題的時候,就想到了無限揹包:

但是這道題的資料範圍是1≤bmin≤bmax≤10^12,使用無限揹包會tle.

那麼就要尋求一種更為高效的方法了,這個時候同餘最短路就應該進入我們的視線了!

按照前面只有x和y兩個條件和有x,y,z三個條件的方法,我們擴充套件到有n個條件上面來。

相較於前面的問題,這個問題多了乙個區間範圍,對於端點值的計算需要特別注意:

如果說dist[i]<=r的時候,可以直接加上(r-dist[i])/a[1]+1,但是如果dist[i]

#include#include#include#include#include#include#include#include#includeusing namespace std;

typedef long long ll;

const int maxn=5e5+100;

const int maxm=6e6+100;

const int inf=0x3f3f3f3f;

const ll inf=(ll)1<<62;

int head[maxn],l;

struct qnode

bool operator

};struct edge

};edge e[maxm];

bool vis[maxn];

ll dist[maxn];

void init()

void dijkstra(int n,int start)}}

}void addedge(int u,int v,int w)

int a[30];

int main()

sort(a+1,a+1+n);

init();

for(int i=0;i

}dijkstra(a[1],0);

ll num_puts=0;

for(int i=0;i

cout<

return 0;

}

同餘最短路小記

前幾天 mns 的時候遇到被卡科技了,然後墊底了 雖說是個極其簡單的東西,但是出於學乙個演算法必須要寫學習筆記的強迫症,還是寫幾行字吧。考慮問題 給定正整數 a 有哪些非負整數能被 a 由非負整數權線性表出。n 2 exgcd?完全揹包?我們發現若 x 可以,則 x ka 1 k in n 也可以。...

演算法模版 同餘最短路

當我們解決形如 sum n a ix i k 的時候,我們可以使用同餘最短路來解決。我們選擇乙個最小的 a i 作為base,然後把其他的 a 表示成 base p left 的形式。我們定義 f i 代表湊出 bmod base 餘 i 的數最小需要多少個 base 而乙個數 p 能被湊出當且僅當...

HDU 6071(同餘最短路)

給你四個點,相鄰兩個點之間有一條連邊。現在問你從 2 號點走到 2 號點的至少為 k 的最短路的長度。因為題目中的 k 比較大,因此一些亂搞的演算法顯然無法通過,而鑑於點數相對來說比較少,因此我們得研究一下這幾個點所蘊涵的性質。我們發現,對於 2 號結點,它有兩條可行的邊,我們設這兩條邊的距離分別為...