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; }