poj2115(扩展欧几里得运用)

来源:互联网 发布:diffrac.eva软件下载 编辑:程序博客网 时间:2024/04/30 12:52

题意:求for(int i=a;i!=b;i+=c,i%=(1<<k))执行的次数;


解法:即求解C*x-(1<<k)*y=b-a;即C*x+K*y=b-a;如果g=gcd(C,K)不能被b-a整除,则说明无解。

         用exgcd()求出一组C/g*x+K/g*y=1的解,然后两边乘上(b-a)/g将求出的x取最小正数输出。


代码:

/******************************************************* author:xiefubao*******************************************************/#pragma comment(linker, "/STACK:102400000,102400000")#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <queue>#include <vector>#include <algorithm>#include <cmath>#include <map>#include <set>#include <stack>#include <string.h>//freopen ("in.txt" , "r" , stdin);using namespace std;#define eps 1e-8const double pi=acos(-1.0);typedef long long LL;const int Max=10100;const int INF=1000000007;LL A, B, C, k;LL exgcd(LL m,LL n,LL &x,LL &y)//求解方程mx+n*y=1的一组解(m,n已知,并且默认m,n互质)方程要灵活运用  {      LL x1,y1,x0,y0;      x0=1; y0=0;      x1=0; y1=1;      x=0; y=1;      LL r=m%n;      LL q=(m-r)/n;      while(r)    {         x=x0-q*x1; y=y0-q*y1;         x0=x1; y0=y1;         x1=x; y1=y;         m=n; n=r; r=m%n;         q=(m-r)/n;     }     return n; }LL gcd(LL a,LL b){    return (a==0)?b:gcd(b%a,a);}int main(){  while(cin>>A>>B>>C>>k)  {      if(A==0&&B==0&&C==0&&k==0)        break;      k=LL(1)<<k;      LL x,y;      LL g=gcd(C,k);      if((B-A)%g!=0)      {          cout<<"FOREVER\n";          continue;      }     exgcd(C/g,k/g,x,y);     k/=g;     cout<<((x*(B-A)/g%k)+k)%k<<endl;  }   return 0;}


0 0
原创粉丝点击