The Luckiest Number[POJ3696]

欢迎大家访问我的老师的OJ———caioj.cn

题面描述

传送门

思路

一句话题意:求至少多少个 8 8 8连在一次组成的正整数是 L ⁡ \operatorname{L} L的倍数。
∵ x 个 8 \because x个8 x8实际上就是 ( 1 0 x − 1 ) / 9 ∗ 8 (10^x-1)/9*8 (10x1)/98,现在我们可以转化一下题意:
求最小的 x x x,满足
L ⁡ ∣ ( 1 0 x − 1 ) / 9 ∗ 8 \operatorname{L} \mid (10^x-1)/9*8 L(10x1)/98

L ⁡ ∣ ( 1 0 x − 1 ) / 9 ∗ 8 ⟷ L ⁡ ∗ 9 ∣ ( 1 0 x − 1 ) ∗ 8 ⟷ 9 L ⁡ gcd ⁡ ( 8 , L ⁡ ) ∣ 1 0 x − 1 ⟷ 1 0 x ≡ 1 ( mod ⁡ 9 L ⁡ gcd ⁡ ( 8 , L ⁡ ) ) \operatorname{L} \mid (10^x-1)/9*8 \longleftrightarrow \operatorname{L}*9 \mid (10^x-1)*8\longleftrightarrow \frac{9\operatorname{L}}{\gcd(8,\operatorname{L})}\mid 10^x-1\longleftrightarrow 10^x \equiv 1(\operatorname{mod} \frac{9\operatorname{L}}{\gcd(8,\operatorname{L})}) L(10x1)/98L9(10x1)8gcd(8,L)9L10x110x1(modgcd(8,L)9L)

引理:

若正整数a,n互质,且满足 a x ≡ 1 ( mod ⁡ n ) a^x\equiv 1(\operatorname{mod} n) ax1(modn)的最小正整数 x 0 x_0 x0 φ ( n ) \varphi(n) φ(n)的约数。

证明:

假设满足 a x ≡ 1 ( mod ⁡ n ) a^x\equiv 1(\operatorname{mod} n) ax1(modn)的最小正整数 x 0 x_0 x0不能整除 φ ( n ) \varphi(n) φ(n)

φ ( n ) = q x 0 + r ( 0 &lt; r &lt; x 0 ) \varphi(n)=qx_0+r(0&lt;r&lt;x_0) φ(n)=qx0+r(0<r<x0).

因为 a x 0 ≡ 1 ( mod ⁡ n ) a^{x_0}\equiv 1(\operatorname{mod} n) ax01(modn)

a q x 0 ≡ 1 ( mod ⁡ n ) a^{qx_0}\equiv 1(\operatorname{mod} n) aqx01(modn)

a φ ( n ) ≡ 1 ( mod ⁡ n ) a^{\varphi(n)}\equiv 1(\operatorname{mod} n) aφ(n)1(modn)

a r ≡ 1 ( mod ⁡ n ) a^r\equiv 1(\operatorname{mod }n) ar1(modn)

与假设 x 0 x_0 x0最小相矛盾。故假设不成立。原命题成立。

证毕。

根据以上引理,我们只要求出 φ ( 9 L / g c d ( L , 8 ) ) \varphi(9L/gcd(L,8)) φ(9L/gcd(L,8)),枚举它的所有约数,用快速幂逐一检查是否满足条件即可。

AC code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#define ll long long
#define gc getchar()
using namespace std;
const int N=15;
ll p[N];int c[N];int t=0;
inline void qr(ll &x)
{
	x=0;int f=1;char c=gc;
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc;}
	while(c>='0'&&c<='9'){x=x*10+(c^48);c=gc;}
	x*=f;
}
ll L;
inline void mul(ll &a,ll b,ll p)
{
	ll c=(long double)a*b/p;
	a=a*b-c*p;
}
inline ll pow_mod(ll a,ll b,ll p)
{
	ll ans=1%p;a%=p;
	while(b)
	{
		if(b&1)mul(ans,a,p);
		b>>=1;mul(a,a,p);
	}
	return ans;
}
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline void div(ll x)
{
	p[0]=0;
	for(ll i=2;i*i<=x;i++)
		if(x%i==0)
		{
			p[++p[0]]=i;
			c[p[0]]=0;
			while(x%i==0)x/=i,++c[p[0]];
		}
	if(x>1)p[++p[0]]=x,c[p[0]]=1;
}
bool dfs(int x,ll ans)
{
	if(x>p[0])
	{
		if(pow_mod(10ll,ans,L)==1)return printf("Case %d: %lld\n",t,ans),true;
		return false;
	}
	ll y=1;
	for(int i=0;i<=c[x];i++)
	{
		if(dfs(x+1,ans*y))return true;
		y*=p[x];
	}
	return false;
}
inline ll phi(ll x)
{
	ll ans=x;
	for(ll 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;
}
int main()
{
	while(qr(L),L)
	{
		L=L*9/gcd(8,L);++t;
		if(gcd(10ll,L)>1){printf("Case %d: 0\n",t);continue;}
		ll phx=phi(L);
		div(phx);
		dfs(1,1);
	}
	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值