墨墨的等式 好题啊

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair < ll,ll > pii;
const long long inf=1000000000017;
const ll maxn=500010;
ll n,lmin,rmax;
ll a[20],d[maxn],vis[maxn];
ll head[maxn],cnt;
struct hyq{
    ll next,to,va;
}e[maxn*10];
void addedge(ll u,ll v,ll d){
    e[++cnt].next=head[u];
    e[cnt].to=v;
    e[cnt].va=d;
    head[u]=cnt;
}
void dijkstra(){
    priority_queue < pii ,vector<pii>,greater<pii> > q;
    d[0]=0;
    q.push(make_pair(d[0],0));
    while( !q.empty() ){
        ll u=q.top().second;
        q.pop();
        if(vis[u]) continue;
        vis[u]=1;
        for(ll i=head[u];i;i=e[i].next){
            ll v=e[i].to;    
            if(d[v]>d[u]+e[i].va){
                d[v]=d[u]+e[i].va;
                q.push(make_pair(d[v],v));
            }
        }
    }
}
ll query(ll u){
    ll cnt=0;
    for(ll i=0;i<a[0];i++){
        if(d[i]<=u) cnt+=(u-d[i])/a[0]+1;
    }
    return cnt;
}
int main(){
    scanf("%lld",&n);
    ll ql,qr;
    scanf("%lld%lld",&ql,&qr);
    a[0]=inf;
    for(ll i=1;i<=n;i++){
        cin>>a[i];
        if(a[i]==0){
            i--,n--;
            continue;//去掉a[i]是0的,对答案没有影响的
        }
        a[0]=min(a[0],a[i]);
    }
    for(ll i=1;i<a[0];i++){
        d[i]=inf;
    }
    for(ll i=0;i<a[0];i++)
      for(ll j=1;j<=n;j++){
      	if(a[j]!=a[0])
      		addedge(i,(i+a[j])%a[0],a[j]);//由于a[j]+c[(i+a[j])%a[0]]<=c[i],这个符合最短路的 查分约束,所以可以建图跑最短路,d[i]的含义就是余数为i的最小的d值
      }
    dijkstra();
    cout<<query(qr)-query(ql-1)<<endl;
}

猜你喜欢

转载自blog.csdn.net/weixin_42759194/article/details/81808895
今日推荐