The Luckiest Number 欧拉函数

The Luckiest Number

Sol:

直接上一波转化:

\[\overbrace{88......88}^x=8*(10^x-1)/9 \]

那么:

\[L\ |\ \overbrace{88......88}^x\iff L\ |\ 8*(10^x-1)/9\iff 9L\ |\ 8*(10^x-1) \]

设d=gcd(L,8),那么上式又等价于:

\[\frac{9L}{d}\ |\ 10^x-1\iff 10^x\equiv1\ (mod\ \frac{9L}{d}) \]

此时可以采取直接枚举x的形式,但是难保证时间,所以需要更好的性质。

引理:

若整数a,n互质,那么有:

\[方程\ a^x\equiv 1\ (mod\ n)\\ 最小正整数解x_0是\phi(n)的约数 \]

证明:

反证法。设存在最小整数解x0,那么令:

\[\phi(n)=q*x_0+r \]

结合欧拉定理可知:

\[a^{\phi(n)}\equiv a^{q*x_0+r}\equiv 1\ (mod\ n) \]

又因为:

\[a^{x_0}\equiv 1\ (mod\ n) \]

所以:

\[a^{q*x_0}\equiv 1\ (mod\ n) \]

所以:

\[a^{q*x_0+r}\equiv a^{q*x_0}*a^r\equiv a^r \equiv 1\ (mod\ n) \]

显然r<x0,与假设矛盾。

证毕

所以可以求出欧拉函数,然后试除法枚举其约数即可。

#include<string>
#include<cstdio>
#include<cstring>
#define RG register
#define IL inline
#define int unsigned long long
#define DB double
#define INF 1e18
using namespace std;

IL int gi() {
	char ch=0;int x=0,fl=0;
	while (ch>'9'||ch<'0') {if (ch=='-') fl=1;ch=getchar();}
	while (ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar();
	return fl?-x:x;
}

int n,d,phi;

IL int getgcd(int x,int y) {return y?getgcd(y,x%y):x;}

IL int multi(int a,int b,int mod)
{
    RG int ans=0;
    a%=mod,b%=mod;
    while(b) {
        if(b&1) ans=(ans+a)%mod;
        b>>=1;
        a=(a+a)%mod;
    }
    return ans;
}

IL int getphi(int x) {
	RG int i,ans=x;
	for (i=2;i*i<=x;++i)
		if (x%i==0) {
			ans=ans/i*(i-1);
			while (x%i==0) x/=i;
		}
	if (x>1) ans=ans/x*(x-1);
	return ans;
}

IL bool quick_pow(int P) {
	RG int x=10,ans=1,mod=9*n/d;
	for (;P;P>>=1,x=multi(x,x,mod))
		if (P&1) ans=multi(ans,x,mod);
	return ans==1;
}

signed main()
{
	RG int i,sum,T=0;
	for (n=gi();n;n=gi()) {
		d=getgcd(8,n);
		if (getgcd(9*n/d,10)==1) {
			sum=phi=getphi(9*n/d);
			for (i=1;i*i<=phi;++i) 
				if (phi%i==0) {
					if (phi!=i*i&&quick_pow(phi/i)) sum=min(sum,phi/i);
					if (quick_pow(i)) {sum=i;break;}
				}
			printf("Case %lld: %lld\n",++T,sum);
		}
		else printf("Case %lld: 0\n",++T);
	}
	return 0;
}
posted @ 2019-04-04 11:10  薄荷凉了夏  阅读(237)  评论(0编辑  收藏  举报