牛客练习赛60-D

传送门:https://ac.nowcoder.com/acm/contest/4853/D

题目大意:给你a,b,c,k。求一个线性方程组a*x+b*y+c*z=k。

  分析:令p=a*x+b*y,则原题有解的条件变成p<=k,且(k-p)%c==0;那么我们就可以对p%c进行分类,显然,对于p%c来说,p肯定去一个较小的值比较好。这个时候,可以对于0-c-1这c个点分别连一些边。比如:i->(i+a)%c,代价为a,i->(a+b)%c,代价为b。这样就能对同一类,得到最小的代价。这样得到代价之后,跑一遍exgcd就可以得到答案了。

#include<bits/stdc++.h>

#define all(x) x.begin(),x.end()
#define fi first
#define sd second
#define lson (nd<<1)
#define rson (nd+nd+1)
#define PB push_back
#define mid (l+r>>1)
#define MP make_pair
#define SZ(x) (int)x.size()

using namespace std;

typedef long long LL;

typedef vector<int> VI;

typedef pair<int,int> PII;

inline LL read(){
    LL res=0, f=1;char ch=getchar();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*f;
}

const int MAXN = 200'005;

const int MOD = 1000000007;

void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
int mulmod(int a, int b){return 1ll*a*b%MOD;}

template<typename T>
void chmin(T& a, T b){if(a>b)a=b;}

template<typename T>
void chmax(T& a, T b){if(b>a)a=b;}

LL a, b, c, k;

LL dd[MAXN];

LL ans[3];

int id;

#define go(e,u) for(int e=head[u];e;e=Next[e])
LL to[MAXN<<1],Next[MAXN<<1],head[MAXN],dis[MAXN<<1],tol;

void add_edge(int u,int v, LL val){
    Next[++tol]=head[u];to[tol]=v;head[u]=tol;dis[tol]=val;
}

void dij(){
    priority_queue<pair<LL, int>> q;

    for(int i=0;i<c;++i)dd[i]=1e18;
    q.push(MP(0,0));
    dd[0]=0;

    while(!q.empty()){
        int u=q.top().sd;q.pop();
        go(e,u){
            int v=to[e];
            if(dd[v]>dd[u]+dis[e]){
                dd[v]=dd[u]+dis[e];
                q.push(MP(-dis[e],v));
            }
        }
    }
}

LL exgcd(LL a, LL b, LL&x, LL& y){
    if(!b){x=1;y=0;return a;}
    LL d=exgcd(b,a%b,x,y);
    swap(x,y);
    y-=a/b*x;
    return d;
}

int main(){
    a=read();b=read();c=read();k=read();

    for(int i=0;i<c;++i){
        add_edge(i,(i+a)%c,a);
        add_edge(i,(i+b)%c,b);
    }

    dij();

    for(int i=0;i<c;++i){
        if(dd[i]<=k&&(k-dd[i])%c==0){
            LL x, y, z, d;
            LL g=exgcd(a,b,x,y);
            x=((dd[i]/g)*x%(b/g)+(b/g))%(b/g);
            y=(dd[i]-a*x)/b;
            z=(k-a*x-b*y)/c;
            cout<<x<<" "<<y<<" "<<z;

            break;
        }
    }

    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/JohnRan/p/12764633.html