[国家集训队]墨墨的等式(同余最短路)

前置题目双倍经验):[洛谷P3403]跳楼机

题目

\([l,r]\)中有多少个b可以使得方程\(\sum{a_ix_i = b}\)有非负整数解\((n\leq 12,l,r\leq 10^{12})\)

思路

问题等价于求\(solve(r)-solve(l-1)\)

考虑怎么求\(solve(r)\),设\(f_i\)表示\(x_1=0\)时(只用其他的数)能得到的最小的模\(a_1\)\(i\)的数
显然,\(f_i\)可以通过加\(a_{2,3,...,n}\)变成转移给\(f_{(i+a_{2,3,4....n})\%a_1}\),将这个关系建边,跑一遍最短路即可得到\(f\)数组
由于\(f\)已经是不用\(a_1\)情况下可以得到的最小的值了,所以给\(f\)只加\(a_1\)就可以得到所有的合法情况;而根据\(f\)的定义,只在\(f_i\)上加\(a_1\)不会使得不同\(i\)出现\(f_i+a_1x_1\)相等的情况,所以分别处理每个\(f_i\)再加起来就行了

\(ans=\sum{((r-f_i)/a_1 +1)}\)

P.S.注意特判存在\(a_i=1\)的情况;可以看出边数与\(a_1\)有关,取最小的\(a\)作为\(a_1\)(当然不取应该也没什么事)

Code

#include<bits/stdc++.h>
#define N 500005
#define Min(x,y) ((x)<(y)?(x):(y))
#define Max(x,y) ((x)>(y)?(x):(y))
using namespace std;
typedef long long ll;
int n,a[15];
ll l,r,dis[N];
bool ccf,vis[N];

struct Edge
{
	int next,to,dis;
}edge[N*12];int head[N],cnt;
void add_edge(int from,int to,int dis)
{
	edge[++cnt].next=head[from];
	edge[cnt].to=to;
	edge[cnt].dis=dis;
	head[from]=cnt;
}

template <class T>
void read(T &x)
{
	char c; int sign=1;
	while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
	while((c=getchar())>='0'&&c<='9') x=(x<<1)+(x<<3)+c-48; x*=sign;
}
void dijkstra()
{
	priority_queue< pair<ll,int> > q;
	memset(dis,100,sizeof(dis));
	memset(vis,0,sizeof(vis));
	dis[0]=0;
	q.push(make_pair(-dis[0],0));
	while(!q.empty())
	{
		int u=q.top().second; q.pop();
		if(vis[u]) continue;
		vis[u]=1;
		for(int i=head[u];i;i=edge[i].next)
		{
			int v=edge[i].to;
			if(dis[v]>dis[u]+edge[i].dis)
			{
				dis[v]=dis[u]+edge[i].dis;
				if(!vis[v]) q.push(make_pair(-dis[v],v));
			}
		}
	}
}
int main()
{
	read(n);read(l);read(r); --l;
	for(int i=1;i<=n;++i) read(a[i]),ccf|=(a[i]==1);
	if(ccf) { cout<<r-l<<endl; return 0; }
	sort(a+1,a+n+1);
	for(int i=0;i<a[1];++i)
	  for(int j=2;j<=n;++j)
	    add_edge(i,(i+a[j])%a[1],a[j]);
	dijkstra();
	ll ans=0;
	for(int i=0;i<a[1];++i)
	{
		if(dis[i]<=r) ans+=(r-dis[i])/a[1]+1;
		if(dis[i]<=l) ans-=(l-dis[i])/a[1]+1;
	}
	cout<<ans<<endl;
	return 0;	
}
posted @ 2019-10-31 17:18  擅长平地摔的艾拉酱  阅读(124)  评论(0编辑  收藏  举报
/*取消选中*/