这道题说实话并不难。。然并卵,我还是不会。。。流下了没技术的泪水.jpg
一开始没想到列方程什么的,就想着循环呗,遇到循环节就错误,然而TLE了。。
附上TLE的代码QAQ:(注意c为0的特判)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
#define ll long long
const int INF=0x3f3f3f3f;
ll a,b,c,k,mod;
map<int,int>mp;//记录循环节
ll Quick_mod(ll a,ll b)//a^b
{
ll ans=1;
while(b)
{
if(b&1)
ans*=a;
b>>=1;
a*=a;
}
return ans;
}
int check()
{
if(b>=a&&((b-a)%c==0))
return ((b-a)/c);
else
return -1;
}
int main()
{
while(scanf("%lld%lld%lld%lld",&a,&b,&c,&k)==4)
{
if(a==0&&b==0&&c==0&&k==0)
break;
if(c==0)
{
if(a==b)
printf("0\n");
else
printf("FOREVER\n");
continue;
}
mp.clear();
mod=Quick_mod(2,k);
ll ans=check();
if(ans!=-1)//一轮
{
printf("%lld\n",ans);
continue;
}
bool sign=true;
mp[a]=1;
while(1)
{
ll t=(mod-a)/c;
if((mod-a)%c!=0)
t++;
a=(a+t*c)%mod;
//cout<<"a="<<a<<endl;
if(mp[a])
{
sign=false;
break;
}
mp[a]=1;
ans=check();
if(ans!=-1)
{
printf("%lld\n",ans+t);
break;
}
}
if(!sign)
printf("FOREVER\n");
}
return 0;
}
然后看了大佬博客Orz:https://blog.csdn.net/lyy289065406/article/details/6648546
发现其实就是个很裸的扩展欧几里得。。式子很简单。。见下图:
然后发现其实2^k可以直接用位运算Orz,附上AC代码:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
#define ll long long
const int INF=0x3f3f3f3f;
ll a,b,c,k,mod;
ll e_gcd(ll a,ll b,ll &x,ll &y)
{
if(a==0&&b==0)
return -1;
if(b==0)
{
x=1;y=0;
return a;
}
ll d=e_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
int main()
{
while(scanf("%lld%lld%lld%lld",&a,&b,&c,&k)==4)
{
if(a==0&&b==0&&c==0&&k==0)
break;
if(c==0)
{
if(a==b)
printf("0\n");
else
printf("FOREVER\n");
continue;
}
mod=(ll)1<<k;
ll A=c,B=mod,C=b-a,x,y;
ll gcd=e_gcd(A,B,x,y);
if(C%gcd!=0)
{
printf("FOREVER\n");
continue;
}
x*=C/gcd;
ll t=B/gcd;
x%=t;
if(x<0)
x+=t;
printf("%lld\n",x);
}
return 0;
}