The Luckiest number(欧拉定理+快速幂+快速乘+公式推导)

Chinese people think of ‘8’ as the lucky digit. Bob also likes digit ‘8’. Moreover, Bob has his own lucky number L. Now he wants to construct his luckiest number which is the minimum among all positive integers that are a multiple of L and consist of only digit ‘8’.

Input
The input consists of multiple test cases. Each test case contains exactly one line containing L(1 ≤ L ≤ 2,000,000,000).

The last test case is followed by a line containing a zero.

Output
For each test case, print a line containing the test case number( beginning with 1) followed by a integer which is the length of Bob’s luckiest number. If Bob can’t construct his luckiest number, print a zero.

Sample Input
8
11
16
0
Sample Output
Case 1: 1
Case 2: 2
Case 3: 0

题意:给定一个数l,求最小的是l倍数的可以用8888…888表示的数的位数,如果不存在这样的数,输出0

思路:
888…888可以表示为 (10^x-1)/9 * 8

=> (10^x-1)/9 * 8 = k * l (k为任意整数,x为答案)

=> (10^x-1) * 8 = k * l * 9

令d=gcd(8,l*9)=gcd(8,l) (8与9互质)

=> (10^x-1) * 8/d ≡ k * 9 * l/d

令p=8/d ,q=k * 9 * l/d

由于p和q互质,所以

=> (10^x-1) ≡0 (mod q)

=>10^x ≡1 (mod q)

由欧拉定理,在10与q互质的情况下
有10^phi(q) ≡ 1(mod q),题目找的是最小的数,那么从小到大枚举phi(q)的因子,如果成立,就输出。

无解的情况就是10与q不互质,即他们的最大公因数不为1

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;
typedef long long ll;
ll q_mul(ll a,ll b,ll p)
{
	ll ans=0;
	while(b)
	{
		if(b&1)
			ans=(ans+a)%p;
		a=(a+a)%p;
		b>>=1;
	}
	return ans;
}
ll q_pow(ll a,ll b,ll p)
{
	ll ans=1;
	while(b)
	{
		if(b&1)
			ans=q_mul(ans,a,p);   //直接乘的话会爆long long,所以用快速乘优化
		a=q_mul(a,a,p);
		b>>=1;
	}
	return ans;
}
ll get_phi(ll n)
{
	ll ans=n;
	for(ll i=2;i<=n/i;i++)
	{
		if(n%i==0)
		{
			ans=ans/i*(i-1);
			while(n%i==0)
				n/=i;
		}
	}
	if(n>1)
		ans=ans/n*(n-1);
	return ans;
}
int main()
{
	int cas=1;
	ll l;
	while(~scanf("%lld",&l)&&l)
	{
		printf("Case %d: ",cas++);
		ll d=__gcd((ll)8,l);
		ll q=l*9/d;
		if(__gcd((ll)10,q)!=1)
		{
			cout<<0<<endl;continue;
		}
		ll phi=get_phi(q),m=sqrt(phi),flag=0;
		ll ans;
		for(ll i=1;i<=m;i++)
		{
			if(phi%i==0)
			{
				if(q_pow(10,i,q)==1)
				{
					ans=i;flag=1;break;
				}
			}
		}
		//这里必须分两次循环找因子,直接从1枚举到phi会t,咱也不知道是什么操作,咱也不敢问,有路过的大佬求解释	
		if(!flag)
		{
			for(ll i=m;i>=1;i--)
			{
				if(phi%i==0)
				{
					ll x=phi/i;
					if(q_pow(10,x,q)==1)
					{
						ans=x;flag=1;break;
					}
				}
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
 }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值