思路:
首先回顾一下扩展欧几里得算法,一般是用来求形如使得ax+by = gcd(a,b)的方程成立的x,y值
其余可以看数学知识章通用模板_北岭山脚鼠鼠的博客-CSDN博客,接下来是一些之前没有提到的补充:
设d==gcd(a,b),对于求一些更一般的方程ax+by=c,这条式子有解当且仅当c%d==0,可以在求一组ax+by=gcd(a,b)的特解(x0,y0)之后将其乘上c/d就是ax+by=c的一组特解。
而这玩意的通解就是x=(c/d)*x0+k*(b/d) y=(c/d)*y0+k*(a/d),其中k为任意整数。
回到题目:
分析题意先假设A是在B的后面,最开始两只青蛙的位置相差(b-a),也就是A要追个(b-a)米,每一次跳跃A追B(m-n)米,在经历了x次跳跃之后的终于到达同一个位置,此时有(m-n)*x==b-a,或者说是已经跳过了一圈变成了(m-n)*x==b-a+L,又或者是已经跳过了k圈,变成了(m-n)*x==b-a+k*L
最终式子调换一下位置就变成了(m-n)*x-k*L==b-a,其中L和(m-n)和(b-a)都是已知量,可以完全用上面说的方法求解,不过求解之前同样要判断有无解,同时m-n的值有可能是负数,最后得到的dyoke能是负的,要转成正数。
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=1e3+10;
typedef long long ll;
ll gcd(ll a,ll b,ll &x,ll &y)
{
if(b==0) { x=1,y=0;return a;}
ll d=gcd(b,a%b,x,y);
ll z=x;
x=y;
y=z-y*(a/b);
return d;
}
int main()
{
ll a,b,m,n,l,x,y;
cin>>a>>b>>m>>n>>l;
ll d=gcd(m-n,l,x,y);
if((b-a)%d) puts("Impossible");
else
{
x*=(b-a)/d;
ll p=l/d;
if(p<0) p=-p;
ll t=p;
cout<<(x%t+t)%t<<endl;
}
return 0;
}
思路:
对于题目中的x个8组合而成的数字可以用一个8*(10^x-1)/9这条式子来表示。
设d为gcd(8,L).
对于题目的要求一定有8*(10^x-1)/9%L==0可得8*(10^x-1)%9L==0可得(10^x-1)%(9L/d)==0可得以下的式子10^x≡1(mod 9L/d),
由欧拉定理a^(φ(n))≡1(mod n)其中可以推出满足a^x≡1(mod n)的最小的x一定是的φ(n)约数,这里不给证明。证明略。
由此,只需要求出欧拉函数φ(9L/d),枚举其所有的约数,用快速幂逐一判断是否满足同余式。
另外有个前提条件,那就是9L/d必须要和10互质,不互质的话欧拉函数不成立,原式子也不成立。
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=1e3+10;
typedef long long ll;
ll get_euler(ll c)
{
ll res=c;
for(int i=2;i<=c/i;i++)
{
if(c%i==0)
{
while(c%i==0) c/=i;
res=res/i*(i-1);
}
}
if(c>1) res=res/c*(c-1);
return res;
}
ll qmul(ll a,ll k,ll b)
{
ll res=0;
while(k)
{
if(k&1) res=(res+a)%b;
a=(a+a)%b;
k>>=1;
}
return res;
}
ll qmi(ll a, ll k,ll p)
{
ll res=1;
while(k)
{
if(k&1) res=qmul(res,a,p); //会爆ll,要用快乘
a=qmul(a,a,p);
k>>=1;
}
return res;
}
int main()
{
int T=1;
ll l;
while(cin>>l,l)
{
ll d=1;
while(l%(d*2)==0&&d*2<=8) d*=2; //获取最大公因数
ll c=9*l/d;
ll res=1e18;
ll p=get_euler(c); //
if(c%2==0||c%5==0) res=0; //判断是否约数
else
for(ll d=1;d*d<=p;d++) //试除法枚举约数
if(p%d==0)
{
if(qmi(10,d,c)==1) res=min(res,d);
if(qmi(10,p/d,c)==1) res=min(res,p/d);
}
printf("Case %d: %lld\n",T++,res);
}
return 0;
}