POJ 3696 : The Luckiest number - 欧拉函数,快速幂[数论好题]

题意:
Bob最喜欢的数字是8,他的幸运数字是能整除L的全8序列的最短长度。
请找到Bob的幸运数字,若无则输出0
例如:L=1,ans=1;L=2,ans=1;L=8,ans=1;L=11,ans=2.

分析:
注意到凡是那种1111111..... 2222222..... 33333.....
之类的序列都可用这个式子来表示:k*(10^n-1)/9
进而简化:8 * (10^n-1)/9=L * k          (k是一个整数)

-->8 * (10^n-1)=9L * 

-->d=gcd(8,L)   8*(10^n-1)/d=9k * L/d

-->令p=8/d   q=9kL/d p*(10^n-1)=q

--->因为p,q互质, 10^n=1 mod q

由欧拉定理可知,当q与10互质的时候,10^(phi(q))=1 mod q

所以无解的时候就是q与10不互质的时候,此外我们求phi(q)的所有因子,按小到大排序,第一个满足10^x =1 mod q的输出。


3696Accepted704K188MSG++1172B
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#define LL long long
using namespace std;
const LL MAX=100000000000;

LL phi(LL n){
	LL x=n,i;
	LL ans=n;
	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;
}

LL multi(LL a,LL b,LL m){//a*b%m
	LL ret=0;
	while(b>0){
		if(b&1){
			ret+=a;
			if(ret>=m)
				ret-=m;
		}
		a+=a;
		if(a>=m)
			a-=m;
		b>>=1;
	}
	return ret;
}

LL quickmod(LL a,LL n,LL MOD){//a^n%MOD
	LL ans=1;
	ans%=MOD;
	for(;n>0;n>>=1,a=multi(a,a,MOD))
		if(n&1)
			ans=multi(ans,a,MOD);
	return ans;
}

int main(){
	int cas=0;
	LL n,i;
	while(~scanf("%lld",&n)&&n){
		int k=0;
		while(n%2==0){
			n/=2;
			k++;
		}
		if(k>3||n%5==0){
			printf("Case %d: 0\n",++cas);
			continue;
		}
		n*=9;
		LL len=phi(n);
		LL ans=MAX;
		for(i=1;i*i<=len;i++){
			if(len%i==0){
				LL f=len/i;
				if(quickmod(10,i,n)==1) ans=min(ans,i);
				if(quickmod(10,f,n)==1) ans=min(ans,f);
			}
		}
		if(ans==MAX) ans=0;
		printf("Case %d: %lld\n",++cas,ans);
	}
	return 0;
}


参考http://blog.csdn.net/sdj222555/article/details/7983898
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值