数论-裴蜀定理-POJ2115-C-Loop
题目:
对于 C 语言的循环语句,形如:
for (variable = A; variable != B; variable += C)
statement;
请问在 k 位存储系统中循环几次才会结束。
若在有限次内结束,则输出循环次数。否则输出死循环。
输入格式
多组数据,每组数据一行四个整数 A,B,C,k。
读入以 0 0 0 0 结束。
输出格式
若在有限次内结束,则输出循环次数。
否则输出 FOREVER。
数据范围
1≤k≤32,
0≤A,B,C<2k
输入样例:
3 3 2 16
3 7 2 16
7 3 2 16
3 4 2 16
0 0 0 0
输出样例:
0
2
32766
FOREVER
题意:
k 位 系 统 中 二 进 制 的 值 仅 保 留 后 k 位 , 即 需 要 将 值 对 2 k 取 模 。 k位系统中二进制的值仅保留后k位,即需要将值对2^k取模。 k位系统中二进制的值仅保留后k位,即需要将值对2k取模。
列 出 关 系 式 : ( A + C x ) m o d 2 k = B 等 价 于 A + C x + 2 k y = B , 即 求 方 程 C x + 2 k y = B − A 的 解 ( x , y ) 。 列出关系式:(A+Cx)mod\ 2^k=B等价于A+Cx+2^ky=B,即求方程Cx+2^ky=B-A的解(x,y)。 列出关系式:(A+Cx)mod 2k=B等价于A+Cx+2ky=B,即求方程Cx+2ky=B−A的解(x,y)。
① 、 判 断 a x + b y = d 是 否 有 整 数 解 即 判 断 g c d ( a , b ) 是 否 为 d 的 因 子 。 ①、判断ax+by=d是否有整数解即判断gcd(a,b)是否为d的因子。 ①、判断ax+by=d是否有整数解即判断gcd(a,b)是否为d的因子。
②
、
要
求
x
的
最
小
正
值
,
通
过
a
x
+
b
y
=
d
的
通
解
形
式
{
x
=
x
0
+
k
b
′
y
=
y
0
−
k
a
′
,
其
中
a
′
=
a
d
,
b
′
=
b
d
。
②、要求x的最小正值,通过ax+by=d的通解形式\begin{cases}x=x_0+kb'\\y=y_0-ka'\end{cases},其中a'=\frac{a}{d},b'=\frac{b}{d}。
②、要求x的最小正值,通过ax+by=d的通解形式{x=x0+kb′y=y0−ka′,其中a′=da,b′=db。
将
x
对
b
′
取
模
,
最
小
正
值
即
(
x
0
%
b
′
+
b
′
)
%
b
′
。
将x对b'取模,最小正值即(x_0\%b'+b')\%b'。
将x对b′取模,最小正值即(x0%b′+b′)%b′。
解题步骤:
- 扩 展 欧 几 里 得 算 法 求 方 程 C x + 2 k y = g c d ( C , 2 k ) 的 解 , 若 g c d ( C , 2 k ) 不 是 B − A 的 因 子 , 则 死 循 环 。 扩展欧几里得算法求方程Cx+2^ky=gcd(C,2^k)的解,若gcd(C,2^k)不是B-A的因子,则死循环。 扩展欧几里得算法求方程Cx+2ky=gcd(C,2k)的解,若gcd(C,2k)不是B−A的因子,则死循环。
- 接 着 将 求 得 的 x 扩 大 B − A g c d ( C , 2 k ) 倍 。 接着将求得的x扩大\frac{B-A}{gcd(C,2^k)}倍。 接着将求得的x扩大gcd(C,2k)B−A倍。
- 最 后 根 据 公 式 求 最 小 值 ( x % b ′ + b ′ ) % b ′ 。 最后根据公式求最小值(x\%b'+b')\%b'。 最后根据公式求最小值(x%b′+b′)%b′。
代码:
#include<cstdio>
#include<iostream>
#define ll long long
using namespace std;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1,y=0;
return a;
}
ll d=exgcd(b,a%b,x,y);
ll tmp=y;
y=x-(a/b)*y;
x=tmp;
return d;
}
int main()
{
ll A,B,C,k;
while(~scanf("%lld%lld%lld%lld",&A,&B,&C,&k),A||B||C||k)
{
ll x,y;
ll b=1ll<<k; ///1要转换为ll
int d=exgcd(C,b,x,y);
if((B-A)%d!=0) cout<<"FOREVER"<<endl;
else
{
int tmp=((B-A)/d);
x*=tmp;
b/=d; ///b要更新为b'
x=(x%b+b)%b;
cout<<x<<endl;
}
}
return 0 ;
}