# POJ3696：The Luckiest number （欧拉定理）

$\frac{9}{8}xL={10}^{k}-1$

$9xL=8\left({10}^{k}-1\right)$

$xl=2\left({10}^{k}-1\right)$

${10}^{k}\equiv 1\left(\phantom{\rule{1em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}l\right)$

$l$$l$是5的倍数，则这个式子无解。否则根据欧拉定理，若$a$$a$$p$$p$互质，则有${a}^{k}\equiv {a}^{k\phantom{\rule{0.667em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}\varphi \left(p\right)}\left(\phantom{\rule{0.667em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}p\right)$$a^k\equiv a^{k\mod\phi(p)}(\mod p)$。换句话说，由于10与$l$$l$互质，所以${10}^{k}$$10^k$$\varphi \left(l\right)$$\phi(l)$为循环。而且由于${10}^{\varphi \left(l\right)}\equiv 1\left(\phantom{\rule{0.667em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}l\right)$$10^{\phi(l)}\equiv 1(\mod l)$，我们只要枚举$\varphi \left(l\right)$$\phi(l)$的因数$e$$e$，查看${10}^{e}$$10^e$是否符合要求即可（即是否有一个更小的循环）。注意快速幂的时候直接相乘会爆long long，要用快速乘。时间复杂度$O\left(T\sqrt{L}{\mathrm{log}}^{2}\left(L\right)\right)$$O(T\sqrt{L}\log^2(L))$

CODE：

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<stdio.h>
#include<algorithm>
using namespace std;

typedef long long LL;

LL n;

LL Phi()
{
LL sn=(long long)floor( sqrt( (double)n )+1e-4 );
LL temp=n,N=n;
for (LL i=2; i<=sn; i++) if (N%i==0)
{
while (N%i==0) N/=i;
temp=temp/i*(i-1LL);
}
if (N>1) temp=temp/N*(N-1);
return temp;
}

LL Mul(LL x,LL y)
{
if (!y) return 0;
LL temp=Mul(x,y>>1);
temp=(temp+temp)%n;
if (y&1) temp=(temp+x)%n;
return temp;
}

LL Pow(LL x,LL y)
{
if (!y) return 1LL;
LL temp=Pow(x,y>>1);
temp=Mul(temp,temp);
if (y&1) temp=Mul(temp,x);
return temp;
}

int main()
{
freopen("3696.in","r",stdin);
freopen("3696.out","w",stdout);

int t=0;
scanf("%I64d",&n);
while (n)
{
t++;
int num=0;
while (!(n&1)) n>>=1,num++;
if ( num>3 || n%5==0 ) printf("Case %d: 0\n",t);
else
{
n*=9;
LL m=Phi();
LL sm=(long long)floor( sqrt( (double)m )+1e-4 );
LL ans=m;
for (LL i=1; i<=sm; i++) if (m%i==0)
{
if (Pow(10,i)==1) ans=min(ans,i);
if (Pow(10,m/i)==1) ans=min(ans,m/i);
}
printf("Case %d: %I64d\n",t,ans);
}
scanf("%I64d",&n);
}

return 0;
}

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客