P2371-[国家集训队]墨墨的等式【同余最短路】
生活随笔
收集整理的這篇文章主要介紹了
P2371-[国家集训队]墨墨的等式【同余最短路】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P2371
題目大意
nnn個aia_iai?,求有多少個b∈[l,r]b\in[l,r]b∈[l,r]滿足∑i=1naixi=b\sum_{i=1}^na_ix_i=b∑i=1n?ai?xi?=b有正整數解。
解題思路
因為有一個a1a_1a1?在,而且x1x_1x1?可以是任意正整數,所以如果在bbb很大的情況下,能夠湊出一個數kkk使得k%a1=b%a1k\% a_1=b\% a_1k%a1?=b%a1?那就能湊出bbb。
所以我們設fif_ifi?表示能湊出的最小的kkk使得k%a1=ik\% a_1=ik%a1?=i。然后最短路轉移即可。
時間復雜度O(a1n)O(a_1n)O(a1?n)
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define ll long long using namespace std; const ll N=5e5+10; struct node{ll to,next,w; }a[N*20]; struct point{ll x,dis; }; bool operator<(point x,point y) {return x.dis>y.dis;} priority_queue<point> q; ll n,m,l,r,tot,f[N],ls[N],w[N]; bool v[N]; void addl(ll x,ll y,ll w){a[++tot].to=y;a[tot].next=ls[x];a[tot].w=w;ls[x]=tot;return; } void Dij(){memset(f,0x3f,sizeof(f));f[0]=0;q.push((point){0,0});while(!q.empty()){ll x=q.top().x;q.pop();if(v[x])continue;v[x]=1;for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;if(f[x]+a[i].w<f[y]){f[y]=f[x]+a[i].w;if(!v[y])q.push((point){y,f[y]});}}}return; } ll get(ll x){ll ans=0;for(ll i=0;i<m;i++)if(x>=f[i])ans+=(x-f[i])/m+1;return ans; } int main() {scanf("%lld%lld%lld",&n,&l,&r);for(ll i=1;i<=n;i++)scanf("%lld",&w[i]);for(ll i=1;i<=n;i++)if(!w[i])swap(w[i],w[n]),n--;sort(w+1,w+1+n);m=w[1];for(ll i=2;i<=n;i++){for(ll j=0;j<m;j++)addl(j,(j+w[i])%m,w[i]);}Dij();printf("%lld",get(r)-get(l-1)); }總結
以上是生活随笔為你收集整理的P2371-[国家集训队]墨墨的等式【同余最短路】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: taptap安卓和苹果互通吗(tapta
- 下一篇: CF786E-ALT【网络流,倍增】