poj3358 Period of an Infinite Binary Expansion



题目大意:

给你一个分数,就他二进制的循环节。求开始循环的点和循环长度。


思路:

poj3358 Period of an Infinite Binary Expansion_第1张图片


已知t*2^phi(r)=t (mod r),先求出phi(r),然后求phi(r)的因子,求一个最小符合条件的。

这样就可以大大缩小了查找的范围。




#include <iostream>
#include <cmath>
#include <stdio.h>
#include <map>
#include <algorithm>
using namespace std;
#define LL long long 
#define min(a,b) a<b?a:b
LL gcd(LL a,LL b)
{
	if(b==0) return a;
	return gcd(b,a%b);
}

LL phi(LL p)
{
	LL ret=p;
	for(LL i=2;i*i<=p;++i)
	{
		if(p%i==0)
		{
			ret=ret/i*(i-1);
			p/=i;
			while(p%i==0) p/=i;
		}
	}
	if(p!=1)
		ret=ret/p*(p-1);
	return ret ;
}
LL pow2_mod(LL k,LL md)
{
	if(k==0) return 1;
	if(k==1)
		return 2%md;
	LL b=pow2_mod(k/2,md);
	b=(b*b)%md;
	if(k&1)
		return 2*b%md;
	return b;
}



int main()
{
	LL p,q,i,cnt=0,period,j;
	while(~scanf("%I64d/%I64d",&p,&q))
	{
		j=1<<29;
		//if(!p){ printf("Case #%I64d: 1,1 \n",++cnt);continue; } 
		period=0;
		LL g=gcd(p,q);
		p/=g;
		q/=g;
		i=1;
		while(q%2==0)
		{
			q/=2;
			i++;
		}
		LL x=phi(q);
		for(int k=2;k*k<=x;++k)
		{
			if(x%k==0)
			{
				if(k<j)
				{
					if(pow2_mod(k,q)==1)
						j=k;
				}
				LL temp=x/k;
				if(temp<j)
					if(pow2_mod(temp,q)==1)
						j=temp;
			}
		}
		if(j>(1<<28))
			period=x;
		else period=j;
		printf("Case #%I64d: %I64d,%I64d \n",++cnt,i,period);
	}
}


你可能感兴趣的:(poj3358 Period of an Infinite Binary Expansion)