POJ 3696 欧拉函数

The Luckiest number
Time Limit: 1000MS Memory Limit: 65536K
   

Description

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,找出一个最小的数m,使得m个8能被l整除,如果不能找到这个数,输出0。

题解:设数字是x,则x个8可以被l整除,因为10^x-1是x个9,所以8/9*(10^x-1)=l*p
即(10^x-1)=0*l*p/8
设m=9*l/gcd(l,8),则存在p1,使得9*l*p/8=m*p1,转化为(10^x-1)=m*p1
求10^x≡1(mode m)的最小解
根据欧拉公式,10^(φ(m))≡1(mod m),因为要求最小解,所以答案是φ(m)的因子
当gcd(L,10)!=1时,方程无解
用快速幂求解即可

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
typedef long long ll;
ll phi(ll n){//欧拉函数
	ll rea=n;
	for(ll i=2;i*i<=n;i++){
		if(n%i==0){
			rea=rea-rea/i;
			do
			n/=i;
			while(n%i==0);
		}
	}
	if(n>1)rea=rea-rea/n;
	return rea;
}
ll multi(ll a,ll b,ll k){//a*b%k  直接乘会爆
	ll ans=0;
	while(b){
		if(b&1){
			ans=(ans+a)%k;
		}
		a=(a<<1)%k;
		b=b>>1;
	}
	return ans;
}
ll quick(ll a,ll k,ll m){//快速幂
	ll ans=1;
	while(k){
		if(k&1){
			ans=multi(ans,a,m);
		}
		a=multi(a,a,m);
		k>>=1;
	}
	return ans;
}
int main(){
	ll l,cas=1;
	while(scanf("%lld",&l)&&l){
		ll m=9*l/__gcd(l,(ll)8);
		printf("Case %lld: ",cas++);
		if(__gcd((ll)10,m)!=1){//无解
			printf("0\n");
			continue;
		}
		ll i,x=phi(m);
		ll flag=0;
		for(i=1;i<=sqrt(x);i++){//先找1-sqrt(x)中的因子
			if(x%i==0){
				if(quick(10,i,m)==1){
					flag=1;
					printf("%lld\n",i);
					break;
				}
			}
		}
		if(!flag){
			for(i=sqrt(x);i>=2;i--){//找sqrt(x)-x的因子
				if(x%i==0){
					if(quick(10,x/i,m)==1){
						printf("%lld\n",x/i);
						break;
					}
				}
			}
		}
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值