同餘最短路問題在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 號結點,它有兩條可行的邊,我們設這兩條邊的距離分別為...