模线性方程

来源:互联网 发布:linux重启weblogic服务 编辑:程序博客网 时间:2024/05/01 08:41

poj2115

大致题意:

对于C的for(i=A ; i!=B ;i +=C)循环语句,问在k位存储系统中循环几次才会结束。

若在有限次内结束,则输出循环次数。

否则输出死循环。

解题思路:

根据题意可得方程:

A+C*X=B (X 再%2^k 就是最后要的结果。)

X=[(B-A) / C]% 2^k

  =[(B-A) % 2^k] / C  (C 不需要%,因为  (0 <= A, B, C < 2k

  =[(B-A)+2^k]%2^k /C

CX=[(B-A)+2^k]%2^k     (说明 (B-A)与CX 关于 2^k 同余)

所以  CX - (B-A) 是 2^k 的整数倍  PS:因为两个%它 余数相同的话,,两个相减就把余数减掉了!

所以得到方程:

C*X+Y*2^k=(B-A)    PS:(Y是倍数,X即为所求)

解法就很清晰了!

先用 exgcd 求出一组解,然后再模一下 求出 最小解就ok了!

FOREVER 的情况就是(B-A)%gcd 不是整数的情况。。即无限循环!!

//Accepted132K0MSC++646B#include<iostream>#include<cstdio>using namespace std;typedef long long ll;void exgcd(ll a,ll b,ll& d,ll& x,ll& y){    if(!b){d=a;x=1;y=0;}    else{exgcd(b,a%b,d,y,x);y-=x*(a/b);}}ll mod(ll a,ll b,ll n){    ll d,x,y,l;    exgcd(a,n,d,x,y);    if(b%d!=0) return -1;    x*=b/d;    l=n/d;    x=(x%l+l)%l;    return x;}int main(){    ll A,B,C,k;    while(~scanf("%I64d%I64d%I64d%I64d",&A,&B,&C,&k))    {        if(A==0&&B==0&&C==0&&k==0) break;        ll flag;        flag=mod(C,B-A,1LL<<k);        if(flag==-1)printf("FOREVER\n");        else printf("%I64d\n",flag);    }    return 0;}


0 0
原创粉丝点击