【luoguP2371】 [国家集训队]墨墨的等式

题目链接

考虑将所有的\(a_1x_1+a_2x_2+……+a_nx_n=B\)\(a_1\)取模,那么所有可达到的B就分为了\(0\)~\(a_1-1\)

如果对\(a_1\)取模为\(k\)的一类\(B\)中最小的\(B\)\(dis[k]\),那么\(dis[k]+a_1,dis[k]+a_1*2,……\)都是可以取到的,

所以对于每一类求最短路,最后统计答案就行了

#include<iostream>
#include<cstring>
#include<cstdio>
#define int long long
using namespace std;

const int N=15;
const int M=500010;
const int INF=0x3f3f3f3f;

int n,a[N],Bmin,Bmax,am=INF;
int dis[M],que[5000010],head,tail;
bool inque[M];

signed main()
{
	scanf("%lld%lld%lld",&n,&Bmin,&Bmax);
	for(int i=1;i<=n;++i)
		scanf("%lld",&a[i]),am=min(am,a[i]);
	memset(dis,0x3f,sizeof(dis));
	dis[0]=0;
	que[++tail]=0;
	while(head<tail){
		int u=que[++head];
		inque[u]=0;
		for(int i=1;i<=n;++i){
			int v=(u+a[i])%am;
			if(dis[v]>dis[u]+a[i]){
				dis[v]=dis[u]+a[i];
				if(!inque[v]){
					que[++tail]=v;
					inque[v]=1;
				}
			}
		}
	}
	int ans=0;
	for(int i=0;i<am;++i)
	  if(dis[i]<=Bmax){
		ans+=(Bmax-dis[i])/am+1;
		if(dis[i]<Bmin)
			ans-=(Bmin-1-dis[i])/am+1;
	}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2019-10-21 12:06  yjk  阅读(111)  评论(0编辑  收藏  举报