poj-3696 The Luckiest number

题意:

给出一个数L,求一个最小的x,使长度为x的888...8这个数整除L;

无解输出0,L<=2*10^9;

题解:

即求满足下式的最小x值:

8/9*(10^x-1)==k*L         (k为正整数)

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

为继续化简,求出r=gcd(L,8);

8/r *(10^x-1)==k*9*L/r

因为8/r与9*L/r互质,9*L这个因式必在(10^x-1)中,所以原式即为:

10^x-1≡0(mod 9*L/r)

10^x≡1(mod 9*L/r)

设q=9*L/r,由欧拉定理得;

10^φ(q)≡1(mod q)

当gcd(q,10)==1时成立,不等于1时无解;

那么φ(q)就是满足题意的的一个解;

但这个解未必是最小的;

实际上,这里的答案也就是10对模q的指数,暂且记为ans;

有定理说明了对任意的d满足10^d≡1(mod q)时,d mod ans==0;

所以φ(q) mod ans == 0;

因为φ(q)可能很大,不能直接枚举ans验证,就将φ(q)分解因式;

对所有的质因子i去验证φ(q)/i是否满足10^φ(q)/i≡1(mod q);

一直枚举完质因子,最后得到的就是ans;

程序实现方面,gcd没什么问题;

为了更快的分解因数(φ函数和最后求解都要用),可以预处理一个素数表(大小到10^5就够了);

验证模线性方程要用到快速幂,但是因为取模数在10^10量级,乘法时有溢出long long的可能;

所以快速幂要套个快速乘,也是一样取模q;

求解上面说了,不再赘述;

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 1000001
using namespace std;
typedef long long ll;
ll pri[N],tot;
bool vis[N];
void init()
{
	for(ll i=2;i<N;i++)
	{
		if(!vis[i])
			pri[++tot]=i;
		for(ll j=1;j<=tot&&i*pri[j]<N;j++)
		{
			vis[i*pri[j]]=1;
			if(i%pri[j]==0)
				break;
		}
	}
}
ll gcd(ll a,ll b)
{
	ll t=a%b;
	while(t)
	{
		a=b,b=t;
		t=a%b;
	}
	return b;
}
ll mul(ll x,ll y,ll mod)
{
	ll ret=0;
	while(y)
	{
		if(y&1)
			ret=(ret+x)%mod;
		x=(x+x)%mod;
		y>>=1;
	}
	return ret;
}
ll pow(ll x,ll y,ll mod)
{
	ll ret=1;
	while(y)
	{
		if(y&1)
			ret=mul(ret,x,mod);
		x=mul(x,x,mod);
		y>>=1;
	}
	return ret;
}
ll eular(ll x)
{
	ll ret=x,i;
	for(i=1;pri[i]*pri[i]<=x;i++)
	{
		if(x%pri[i]==0)
		{
			while(x%pri[i]==0)
				x/=pri[i];
			ret/=pri[i],ret*=pri[i]-1;
		}
	}
	if(x!=1)
		ret/=x,ret*=x-1;
	return ret;
}
ll Ans(ll q)
{
	if(gcd(q,10)!=1)	return 0;
	ll ret=eular(q),temp=ret,cnt;
	for(ll i=1;pri[i]*pri[i]<=temp;i++)
	{
		if(temp%pri[i]==0)
		{
			cnt=0;
			while(temp%pri[i]==0)
				cnt++,temp/=pri[i];
			while(cnt)
			{
				if(pow(10,ret/pri[i],q)==1)
				{
					ret/=pri[i],cnt--;
				}
				else
					break;
			}
		}
	}
	if(temp!=1)
		if(pow(10,ret/temp,q)==1)
			ret/=temp;
	return ret;
}
int main()
{
	int c=1;
	ll n,i,j,k,p,q;
	init();
	while(scanf("%lld",&n)&&n)
	{
		q=9*n/gcd(n,8);
		printf("Case %d: %lld\n",c++,Ans(q));
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-10 02:03:22

poj-3696 The Luckiest number的相关文章

poj 3696 The Luckiest number 欧拉函数在解a^x=1modm的应用

题意: 给一个L,求长度最小的全8数满足该数是L的倍数. 分析: 转化为求方程a^x==1modm.之后就是各种数学论证了. 代码: //poj 3696 //sep9 #include <iostream> #include <algorithm> using namespace std; typedef long long ll; ll L; ll factor[65536]; ll mul(ll x,ll y,ll p) { ll ret=0; while(y){ if(y&

poj 3696 欧拉函数

poj 3696 题意: 给出一个数字L,求出最短的888...8能被L整除,输出最短的长度. 限制: 1 <= L <= 2*10^9 思路: 设x为最小长度 888...8=(10^x-1)/9*8 由题意得: (10^x-1)/9*8 % L=0 -> (10^x-1)*8 % (9L) = 0 -> (10^x-1) % (9L/gcd(L,8)) = 0 -> 10^x % (9L/gcd(L,8)) = 1 这个是一个离散对数的问题,第一个想到的是用拓展BSGS做

The Luckiest number(hdu2462)

The Luckiest number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1163    Accepted Submission(s): 363 Problem Description Chinese people think of '8' as the lucky digit. Bob also likes digit '

poj_3696_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

POJ_3696 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 consi

POJ3696 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

poj The Luckiest number

                                     The Luckiest numbe 题目: 在满足|x| + |y|最小时候,让a*|x| + b*|y|最小.求:|x| + |y|最小值. 算法: 同余式的求解运用. 解体步骤: 1.先用gcd判断是否有解.(c%g == 0有解) 2.对式子求最简式.a' = a/g ; b' = b/g: c' = c/g; 3.运用扩展欧几里得求解x,y的值. 4.判断当x,y分别求得最小正整数解时候的大小. 5.确定最后答案

[POJ3696]The Luckiest number(数论)

题目:http://poj.org/problem?id=3696 题意:给你一个数字L,你要求出一个数N,使得N是L的倍数,且N的每位数都必须是8,输出N的位数(如果不存在输出0) 分析: 首先我们假设N是x个8组成的 那么88888...888=kL 提个8出来:8*111..1111=kL ① 因为题目只要求x的值,所以要弄出关于x的方程 11...111可以写成(10^k-1)/9 于是①变成了8(10^x-1)=9kL ② 再来回顾下题目,②式中x和k是变量,且都属于正整数,要根据②式

POJ 2104:K-th Number(整体二分)

http://poj.org/problem?id=2104 题意:给出n个数和m个询问求区间第K小. 思路:以前用主席树做过,这次学整体二分来做.整体二分在yr大佬的指点下,终于大概懂了点了.对于二分能够解决的询问,如果有多个,那么如果支持离线处理的话,那么就可以使用整体二分了. 在这题二分可行的答案,根据这个答案,把询问操作丢在左右两个队列里面分别递归继续按这样处理.注释里写的很详细. 1 #include <iostream> 2 #include <cstdlib> 3 #

【POJ 2104】K-th Number

Description You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array