现在的位置: 首页 > 综合 > 正文

poj3358 Period of an Infinite Binary Expansion

2012年12月28日 ⁄ 综合 ⁄ 共 1612字 ⁄ 字号 评论关闭

题意:

输入一个有理数p/q(保证是一个小数),然后将其小数部分用二进制表示。求出在此种表示下的循环起点和循环节长度

比如1/10,化为二进制就是

0.000110011

起点就是小数点后第二位,循环节是0011,长度为4

解法:

比如1/10,用乘二法,2/10,4/10,8/10,6/10,2/10

其中1*2^1=1*2^5(mod10)

用p代表分子,q代表分母,i代表一个位置,j代表一个位置,比如在1/10中,i为1,j为5,一下的p和q均为最简式

那么我们要求的就是

p*2^i=p*2^j(modq)

化简得2^(j-i)=1(modq)

观察得q能被2整除多少次,i就是多少,而且i就是循环开始位置的前一位,然后将q不断除以2直到不能整除

求出i后,另k为j-i

那么所求为

2^k=1(modq)

用欧拉定理就可解决上式

#include<algorithm>
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
long long Mulmod(const long long &a,long long b,const long long &n)//a*b%n
{
    long long res=0,tmp=a%n;
    while(b>0)
    {
        if (b&1)
            if ((res+=tmp)>n) res-=n; 
        if ((tmp<<=1)>n) tmp-=n;
        b>>=1;
    }
    return res;
}
long long Pow(long long a,long long d,const long long &n)//a^d%n
{ 
    long long res=1;
    while (d>0)
    { 
        if (d&1) res=Mulmod(res,a,n);
        a=Mulmod(a,a,n); 
        d>>=1; 
    }
    return res; 
}
long long euler(long long n)//求n的欧拉函数
{
    long long ans=1,i;
    for(i=2;i*i<=n;i++)
        if (n%i==0)
        {
            ans*=i-1; n/=i;
            while(n%i==0)
            { ans*=i; n/=i; }
        }
    if (n>1) ans*=n-1;
    return ans;
}
long long gcd(long long a,long long b)//求a,b的最大公约数
{
	if(b==0)
	{
		return a;
	}
	return gcd(b,a%b);
}
int numOfYinzi;
int yinzi[100000];//0,1,,,numOfYinzi-1
void divide(int n)//将n分解质因子存在yinzi数组中
{
	for(int i=2;i*i<=n;i++)
	{
		if(n%i==0)
		{
			yinzi[numOfYinzi++]=i;
			yinzi[numOfYinzi++]=n/i;
		}
	}
	yinzi[numOfYinzi++]=n;
}
int main()
{
	//freopen("in.txt","r",stdin);
	string input;
	long long counter=1;
	long long p,q;
	while(scanf("%lld/%lld",&p,&q)!=-1)
	{
		numOfYinzi=0;
		long long g=gcd(p,q);
		p/=g;
		q/=g;
		//化简为最简式
		long long i=0,j;//i为起始位置的前一位置
		while(!(q&1))//q能被2整除
		{
			q/=2;
			i++;
		}
		long long eulerQ=euler(q);//q的欧拉函数
		long long k;
		divide(eulerQ);
		sort(yinzi,yinzi+numOfYinzi);
		for(k=0;k<numOfYinzi;k++)
		{
			if(Pow(2,yinzi[k],q)==1)
			{
				break;
			}
		}
		cout<<"Case #"<<counter++<<": "<<i+1<<','<<yinzi[k]<<endl;
	}
	return 0;
}





抱歉!评论已关闭.