正题
题目链接:https://www.luogu.com.cn/problem/P2371
题目大意
nnn个aia_iai,求有多少个b∈[l,r]b\in[l,r]b∈[l,r]满足∑i=1naixi=b\sum_{i=1}^na_ix_i=b∑i=1naixi=b有正整数解。
解题思路
因为有一个a1a_1a1在,而且x1x_1x1可以是任意正整数,所以如果在bbb很大的情况下,能够凑出一个数kkk使得k%a1=b%a1k\% a_1=b\% a_1k%a1=b%a1那就能凑出bbb。
所以我们设fif_ifi表示能凑出的最小的kkk使得k%a1=ik\% a_1=ik%a1=i。然后最短路转移即可。
时间复杂度O(a1n)O(a_1n)O(a1n)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
const ll N=5e5+10;
struct node{ll to,next,w;
}a[N*20];
struct point{ll x,dis;
};
bool operator<(point x,point y)
{return x.dis>y.dis;}
priority_queue<point> q;
ll n,m,l,r,tot,f[N],ls[N],w[N];
bool v[N];
void addl(ll x,ll y,ll w){a[++tot].to=y;a[tot].next=ls[x];a[tot].w=w;ls[x]=tot;return;
}
void Dij(){memset(f,0x3f,sizeof(f));f[0]=0;q.push((point){0,0});while(!q.empty()){ll x=q.top().x;q.pop();if(v[x])continue;v[x]=1;for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;if(f[x]+a[i].w<f[y]){f[y]=f[x]+a[i].w;if(!v[y])q.push((point){y,f[y]});}}}return;
}
ll get(ll x){ll ans=0;for(ll i=0;i<m;i++)if(x>=f[i])ans+=(x-f[i])/m+1;return ans;
}
int main()
{scanf("%lld%lld%lld",&n,&l,&r);for(ll i=1;i<=n;i++)scanf("%lld",&w[i]);for(ll i=1;i<=n;i++)if(!w[i])swap(w[i],w[n]),n--;sort(w+1,w+1+n);m=w[1];for(ll i=2;i<=n;i++){for(ll j=0;j<m;j++)addl(j,(j+w[i])%m,w[i]);}Dij();printf("%lld",get(r)-get(l-1));
}