BZOJ2118 墨墨的等式 最短路

题意:给定N个正整数ai,求[L,R]中能凑出多少个数

题解:

首先取最小的ai,如果k*ai+x合法,则(k+n)ai+x均合法(其中L<=(k+n)ai+x<=R)

因此对于每一个x,我们只需要求出最小的k,然后就能算出所有的合法解的数量。

至于算k,用最短路就好

#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define NUM pair<ll,int>

const int MAXN=12+2;
const int MAXM=500000+2;
struct HASH{
    int u,w;
    HASH *next;
    HASH(){}
    HASH(int _u,int _w,HASH *_next):u(_u),w(_w),next(_next){}
}*table[MAXM],mem[2*MAXM];
int N,a[MAXN],cnt;
ll L,U,d[MAXM],ans;
bool flag[MAXM];
priority_queue<NUM,vector<NUM>,greater<NUM> >q;

void Insert(int u,int v,int w){ table[u]=&(mem[cnt++]=HASH(v,w,table[u]));}

void Dijkstra(){
    memset(d,0X7F,sizeof(d));
    d[0]=0;

    q.push(make_pair(0,0));
    while(!q.empty()){
        int x=q.top().second;q.pop();

        if(flag[x]) continue;
        flag[x]=1;

        for(HASH *p=table[x];p;p=p->next)
            if(d[p->u]>d[x]+p->w){
                d[p->u]=d[x]+p->w;
                q.push(make_pair(d[p->u],p->u));
            }
    }
}

int main(){
    scanf("%d %lld %lld",&N,&L,&U);
    for(int i=1;i<=N;i++) scanf("%d",a+i);
    sort(a+1,a+N+1);
    for(int i=0;i<a[1];i++)
        for(int j=2;j<=N;j++)
            Insert(i,(a[j]+i)%a[1],a[j]);

    Dijkstra();
    for(int i=0;i<a[1];i++)
        if(d[i]<=U){
            ll l=max(0LL,(L-d[i])/a[1]),r=(U-d[i])/a[1];
            if(l*a[1]+d[i]<L) l++;
            if(r*a[1]+d[i]>U) r--;
            ans+=r-l+1;
        }
    printf("%lld\n",ans);

    return 0;
}
View Code

 

posted @ 2017-02-27 22:48  WDZRMPCBIT  阅读(167)  评论(0编辑  收藏  举报