zoukankan      html  css  js  c++  java
  • 牛客练习赛60 D 斩杀线计算大师

    LINK:斩杀线计算大师

    给出a,b,c三个值 求出 ax+by+cz=k的x,y,z的正整数解 保证一定有解。

    考虑两个数的时候 ax+by=k 扩展欧几里得可以解决。

    三个数的时候 一个暴力的想法暴力枚举c的系数z 然后进行计算扩欧 期望复杂度是过不了的 但是数据保证有解那么就很容易通过了。

    考虑 (a,b)|k-cz 设g=(a,b) Tg=k-cz 对于这个式子 我们发现z越小那么tg越大 那么a和b更容易是正整数 且g|k-sz是ax+by=k-cz的必要条件。

    所以我们解出 Tg=k-cz这个式子的答案并且让z尽可能的小 可以发现此时一定有解 且构造出的解cz一定比其他cz更优于满足答案。

    所以两次扩展欧几里得解决。

    const ll MAXN=1010;
    ll a,b,c,k;
    ll x,y;
    inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    inline ll exgcd(ll a,ll b)
    {
    	if(!b){x=1;y=0;return a;}
    	ll w=exgcd(b,a%b);
    	ll z=x;x=y;y=z-a/b*y;
    	return w;
    }
    signed main()
    {
    	freopen("1.in","r",stdin);
    	get(a);get(b);get(c);get(k);
    	ll g=gcd(a,b);
    	ll gg=exgcd(g,c);
    	ll s=k/gg;
    	y=y*s;x=x*s;
    	ll w1=g/gg;
    	ll w2=c/gg;
    	if(y<0)
    	{
    		ll sum=(-y)%w1==0?(-y)/w1:(-y)/w1+1;
    		y=y+sum*w1;
    		x=x-sum*w2;
    	}
    	ll sum=y/w1;
    	y-=sum*w1;
    	x+=sum*w2;
    	ll cc=y;
    	k=x*g;
    	gg=exgcd(a,b);
    	s=k/gg;
    	y=y*s;x=x*s;
    	w1=a/gg;w2=b/gg;
    	if(x<0)
    	{
    		ll sum=(-x)%w2==0?(-x)/w2:(-x)/w2+1;
    		x=x+sum*w2;
    		y=y-sum*w1;
    	}
    	if(y<0)
    	{
    		ll sum=(-y)%w1==0?(-y)/w1:(-y)/w1+1;
    		x=x-sum*w2;
    		y=y+sum*w1;
    	}
    	printf("%lld %lld %lld
    ",x,y,cc);
    	return 0;
    }
    

    虽然正解比暴力长很多 但是打完之后感觉对扩展欧几里得的理解更深了。
    以后写的话不会很迷了。

    果然做难题是搞定知识的重要途径。

  • 相关阅读:
    【JS教程08】数组及操作方法
    【JS教程07】事件属性及匿名函数
    【JS教程06】操作元素
    【JS教程05】获取元素的方法
    【JS教程04】条件语句
    多线程环境下非安全Dictionary引起的“已添加了具有相同键的项”问题
    GPT分区基础知识及如何在GPT分区上安装WIN7
    Jenkins TFS配置
    windows查看端口占用命令
    VS2015企业版序列号
  • 原文地址:https://www.cnblogs.com/chdy/p/12590291.html
Copyright © 2011-2022 走看看