C 循环

32 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 3 天,点击查看活动详情

题目

对于 C 语言的循环语句,形如:

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

请问在 k� 位存储系统中循环几次才会结束。

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

输入格式

多组数据,每组数据一行四个整数 A,B,C,k�,�,�,�。

读入以 0 0 0 0 结束。

输出格式

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

否则输出 FOREVER。

数据范围

1≤k≤321≤�≤32,
0≤A,B,C<2k0≤�,�,�<2�

输入样例:

3 3 2 16
3 7 2 16
7 3 2 16
3 4 2 16
0 0 0 0

输出样例:

0
2
32766
FOREVER

分析

这题看似有点难,其实不难,只要了解了扩展欧几里得算法的本质,这题就变得很简单了,首先我们要知道裴蜀定理,裴蜀定理就是说对于任意正整数a和b,一定可以拼出他们的最大公约数gcd,而且gcd是他们所能拼出来的的最小正整数,我们可以用exgcd找到这样一组解,然后再由相应的方式解出通解,那么最下值就是这个x%(k/gcd)。

代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <map>
#include <set>
#include <iomanip>
#include <cmath>
#include <unordered_map>
#include <stack>
#include <queue>
#define ll long long
#define lowbit(x) x&(-x)
using namespace std;
typedef pair<int,int> PII;
typedef pair<string,int> PSI;
ll a,b,c,k;
ll exgcd(ll a,ll b,ll &x,ll &y){//ecgcd过程
    if(!b){
        x=1,y=0;
        return a;
    }
    ll d=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}
ll qmi(ll x,ll y,int mod){//快速幂
    ll res=1;
    while(y){
        if(y&1) res=res*x%mod;
        y>>=1;
        x=x*x%mod;
    }
    return res;
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    while(cin>>a>>b>>c>>k){
        if(!a && !b && !c && !k){
            break;
        }
        ll gc=1ll<<k;
        ll x,y;
        ll d=exgcd(c,gc,x,y);
        if((b-a)%d) cout<<"FOREVER"<<"\n";
        else{
            x*=(b-a)/d;
            gc/=d;
            cout<<(x%gc+gc)%gc<<"\n";、、防止输出负数
        }
        
    }
    return 0;
}

希望对大家有所帮助qaq()