【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;
}

猜你喜欢

转载自www.cnblogs.com/yjkhhh/p/11712682.html