Live2D

【国家集训队】墨墨的等式

墨墨突然对等式很感兴趣,他正在研究
a1x1+a2x2+...+anxn=B存在非负整数解的条件
他要求你编写一个程序 ,给定N、{an}、 以及B的取值范围
求出有多少B可以使等式存在非负整数解

集训队的神题……
怎么看都以为是数论题,结果是同余最短路……
通过对所有数%k,跑最短路,求出在%k意义下的最小数
那么在%k意义下的更大的数也一定可以抵达
而且有点卡常,所以跑spfa的时候不用建边,直接跑就好了
实乃思维神题啊……

代码:

#include<bits/stdc++.h>
#define N 500005
#define inf (1LL<<60)
#define ll long long
using namespace std;

ll n,l,r,a[13],ans=0;

template<class T>inline void read(T &res)
{
	char c;T flag=1;
	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
	while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
} 

ll dis[N];
bool vis[N];
queue<ll> q;
void spfa(int s)
{
	for(register int i=0;i<=a[1];++i) dis[i]=inf;
	memset(vis,0,sizeof(vis));
	q.push(s);
	dis[s]=0;
	vis[s]=1;
	while(!q.empty())
	{
		int u=q.front();q.pop();vis[u]=0;
		for(register int i=2;i<=n;++i)
		{
			int v=(u+a[i])%a[1];
			if(dis[v]>dis[u]+a[i])
			{
				dis[v]=dis[u]+a[i];
				if(!vis[v])
				{
					q.push(v);
					vis[v]=1;
				}
			}
		}
	}
}

int main()
{
	read(n);read(l);read(r);
	for(register int i=1;i<=n;++i) read(a[i]);
	sort(a+1,a+n+1);
	spfa(0);
	for(register int i=0;i<a[1];++i)
	{
		if(dis[i]<=r)
		{
			if(dis[i]>=l) ans+=(r-dis[i])/a[1]+1;
			else ans+=(r-dis[i])/a[1]+1,ans-=(l-dis[i]+a[1]-1)/a[1];
		}
	}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2019-10-11 19:22  tqr06  阅读(165)  评论(0编辑  收藏  举报