题意:给出一个分数,求出这个分数用二进制表示的时候的循环节长度还有第一个开始循环的位置
思路:同余方程,欧拉定理
错误:快速幂的时候溢出了,输出少加了一个逗号。
代码如下:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<vector>
using namespace std;
int ans[30000];
bool valid[100000];
int tot=0;;
void getPrime()
{
memset(valid,true,sizeof(valid));
valid[1]=false;
valid[0]=false;
for(int i=2;i<=99999;++i)
{
if(valid[i])
{
tot++;
ans[tot]=i;
}
for(int j=1;((j<=tot)&&(i*ans[j]<=99999));j++)
{
valid[i*ans[j]]=false;
if(i%ans[j]==0)break;
}
}
}
int gcd(int a,int b)
{
int c=a%b;
for(;c!=0;c=a%b)
{
a=b;b=c;
}
return b;
}
int mul_pow(int a,int b,int m)
{
a%=m;
int ret=1;
while(b)
{
if(b&1)
ret=(long long)ret*a%m;
b>>=1;
a=(long long)a*a%m;
}
return ret;
}
int phi(int n)
{
int tmp=(sqrt(n)+1);
int rea=n;
for(int i=1;ans[i]<=tmp;++i)
{
if(n%ans[i]==0)
{
rea=rea-rea/ans[i];
while(n%ans[i]==0)
{
n/=ans[i];
}
}
}
if(n>1)rea=rea-rea/n;
return rea;
}
vector<int> a;
void factor(int n)
{
int tmp=sqrt(n)+1;
for(int i=1;ans[i]<=tmp;++i)
{
if(n%ans[i]==0)
{
a.push_back(ans[i]);
while(n%ans[i]==0)n/=ans[i];
}
}
if(n!=1){
a.push_back(n);
}
}
int main(){
// freopen("data.txt","r",stdin);
int kase=0;
int p,q;
getPrime();
while(scanf("%d/%d",&p,&q)!=EOF)
{
if(p==0)
{
printf("Case #%d: 1,1\n",++kase);
continue;
}
// cout<<p<<' '<<q<<endl;
a.clear();
int d=gcd(p,q);
p=p/d;
q=q/d;
int qq=q;
int first=0;
while(qq%2==0)
{
first++;
qq>>=1;
}
int period=phi(qq);
factor(period);
for(int i=0;i<a.size();++i)
{
while(period%a[i]==0&&mul_pow(2,period/a[i],qq)==1)
{
period/=a[i];
}
}
printf("Case #%d: ",++kase);
printf("%d,%d\n",first+1,period);
}
return 0;
}