您的位置:首页 > 其它

poj 3696 The Luckiest number

2013-08-06 10:41 316 查看
题目链接http://poj.org/problem?id=3696

题目描述:求能整除L的全8序列的最短长度

题目分析:设该数字为x   8/9*(10^x-1)=L*p  即 (10^x-1)=9*L*p/8  设m=9*L/gcd(L,8),则存在p1,9*L*p/8=m*p1;方程转化为(10^x-1)=m*p1 即求10^x=1(mod m)的最小解

欧拉公式 10^phi(m)=1(mod m) 求最小解 则答案肯定是phi(m)的因子 然后枚举phi(m)的因子即可    当gcd(10,m)!=1时, 无解

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define ll long long
using namespace std;
ll gcd(ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
int i,j,k,x,y,z;
ll m,mo;
ll mul1(ll a,ll b)
{
ll n=0;
while (b)
{
if (b&1)
n=(n+a)%mo;
a=a*2%mo;
b=b>>1;
}
return n;
}
ll mul(ll x)
{
ll n=1,m=10;
while (x>0)
{
if (x&1)n=mul1(n,m);
m=mul1(m,m);
x=x>>1;
}
return n;
}
int main()
{
int ca=0;
while (scanf("%I64d",&m)&&m)
{
printf("Case %d: ",++ca);
m=m*9/gcd(m,8);
if (gcd(m,10)!=1)
{
printf("0\n");continue;
}
mo=m;
ll rear=m,n=m;
ll p[50][2];int k=0;
for (ll i=2;i*i<=n;i++)
if (n%i==0)
{
rear=rear-rear/i;
do
n/=i;
while(n%i==0);
}
if (n>1)rear=rear-rear/n;//求phi(m)
n=rear;
for (ll i=2;i*i<=n;i++)//对phi(m)进行因式分解
if (n%i==0)
{
p[k][0]=i;
p[k][1]=0;
do
{
n/=i;
p[k][1]++;
}while (n%i==0);
k++;
}
if (n>1)
{
p[k][0]=n;p[k][1]=1;k++;
}
for (i=0;i<k;i++)
for (int j=1;j<=p[i][1];j++)
if (mul(rear/p[i][0])==1)//求最小的x 则满足条件 即除掉。。
rear/=p[i][0];
printf("%I64d\n",rear);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数论 poj