POJ - 2115C Looooops 扩展欧几里得(做的少了无法一眼看出)

题目大意&&分析:

for (variable = A; variable != B; variable += C)

statement;
这个循环式子表示a+c*n(n为整数)==b是停止循环,题目中要求(a+c*n)%2^k=b时停止循环;所以我们可以得到一个形如ax+by=c的方程式:a+c*n=b+2^k*m;
通过移项:c*x-2^k*m=b-a;
可以直接套exgcd模板了:

代码:
#include <iostream>

using namespace std;
typedef long long ll;
ll d;
ll x,y;
void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
    if (!b)
    {
        x=1;y=0;d=a;return ;
    }
    else
    {
        exgcd(b,a%b,d,y,x);
        y-=(a/b)*x;
    }
}
int main()
{
    ll a,b,c,k;
    while (cin>>a>>b>>c>>k&&(a+b+c+k))
    {
        ll C=(ll)1<<k;                //注意别写成ll k=(ll)1<<k; 会出错就是了;

        exgcd(c,C,d,x,y);
        //cout<<x<<y<<endl;
        if ((b-a)%d)
        {
            cout<<"FOREVER"<<endl;
        }
        else
        {
            x=x*(b-a)/d;
            C/=d;                    //1
            x=(x%C+C)%C;              //2
            cout<<x<<endl;
        }
    }
}

这两行用于求出最小正整数解,ax+by=c;  a,b互素,则ax1+by1=ax2+by2;那么(x1-x2)一定是b的整数倍,

所以当x>0时,x%b即为所求;

x<0时,x%b+b即为所求,二者综合就是(x%b+b)%b可以得出最小正整数解;

posted @ 2017-05-21 11:05  飞将-奉先  阅读(154)  评论(0编辑  收藏  举报