「BZOJ2118」墨墨的等式
Description
墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N、{an}、以及B的取值范围,求出有多少B可以使等式存在非负整数解。
Input
输入的第一行包含3个正整数,分别表示N、BMin、BMax分别表示数列的长度、B的下界、B的上界。输入的第二行包含N个整数,即数列{an}的值。
Output
输出一个整数,表示有多少b可以使等式存在非负整数解。
Sample Input
2 5 10
3 5
3 5
Sample Output
5
HINT
对于100%的数据,N≤12,0≤ai≤5*10^5,1≤BMin≤BMax≤10^12。
题解
找一个最小的ai,设其为mn,若x为合法的B,则x+mn也合法
设bi为最小的x,满足\(x~mod~mn~=~i\)
用dijsktra+堆求一下bi,枚举i计算答案贡献
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
#include<map> #include<cmath> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define inf 1000000000 #define ll long long #define pa pair<ll,int> using namespace std; ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,cnt,a[15],last[500005]; ll dis[500005]; ll L,R,ans; bool vis[500005]; struct edge{ int to,next,v; }e[5000005]; priority_queue<pa,vector<pa>,greater<pa> >q; void insert(int u,int v,int w) { e[++cnt]=(edge){v,last[u],w};last[u]=cnt; } void dijkstra() { for(int i=0;i<a[1];i++)dis[i]=(ll)1e60;dis[0]=0; q.push(make_pair(0,0)); while(!q.empty()) { int now=q.top().second;q.pop(); if(vis[now])continue;vis[now]=1; for(int i=last[now];i;i=e[i].next) if(dis[now]+e[i].v<dis[e[i].to]) { dis[e[i].to]=dis[now]+e[i].v; q.push(make_pair(dis[e[i].to],e[i].to)); } } } int main() { n=read();L=read();R=read(); for(int i=1;i<=n;i++)a[i]=read(); 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(dis[i]<=R) { ll l=max(0LL,(L-dis[i])/a[1]); if(l*a[1]+dis[i]<L)l++; ll r=(R-dis[i])/a[1]; if(r*a[1]+dis[i]>R)r--; ans+=r-l+1; } printf("%lld\n",ans); return 0; } |
Subscribe