Problem Description
In the math class, the evil teacher gave you one unprecedented problem!
Here f(n) is the n-th fibonacci number (n >= 0)! Where f(0) = f(1) = 1 and for any n > 1, f(n) = f(n - 1) + f(n - 2). For example, f(2) = 2, f(3) = 3, f(4) = 5 ...
The teacher used to let you calculate f(n) mod p where n <= 10^18 and p <= 10^9, however , as an ACMER, you may just kill it in seconds! The evil teacher is mad about this. Now he let you find the smallest integer m (m > 0) such that for ANY non-negative integer n ,f(n) = f(n + m) (mod p) . For example, if p = 2, then we could find know m = 3 , f(0) = f(3) = 1(mod 2), f(1) = f(4) (mod 2) ....
Now the evil teacher will only give you one integer p( p <= 2* 10^9), will you tell him the smallest m you can find ?
Here f(n) is the n-th fibonacci number (n >= 0)! Where f(0) = f(1) = 1 and for any n > 1, f(n) = f(n - 1) + f(n - 2). For example, f(2) = 2, f(3) = 3, f(4) = 5 ...
The teacher used to let you calculate f(n) mod p where n <= 10^18 and p <= 10^9, however , as an ACMER, you may just kill it in seconds! The evil teacher is mad about this. Now he let you find the smallest integer m (m > 0) such that for ANY non-negative integer n ,f(n) = f(n + m) (mod p) . For example, if p = 2, then we could find know m = 3 , f(0) = f(3) = 1(mod 2), f(1) = f(4) (mod 2) ....
Now the evil teacher will only give you one integer p( p <= 2* 10^9), will you tell him the smallest m you can find ?
Input
The first line is one integer T indicates the number of the test cases. (T <=20)
Then for every case, only one integer P . (1 <= P <= 2 * 10^9, the max prime factor for P is no larger than 10^6)
Then for every case, only one integer P . (1 <= P <= 2 * 10^9, the max prime factor for P is no larger than 10^6)
Output
Output one line.
First output “Case #idx: ”, here idx is the case number count from 1.Then output the smallest m you can find. You can assume that the m is always smaller than 2^64 .
First output “Case #idx: ”, here idx is the case number count from 1.Then output the smallest m you can find. You can assume that the m is always smaller than 2^64 .
Sample Input
5 11 19 61 17 67890
Sample Output
Case #1: 10 Case #2: 18 Case #3: 60 Case #4: 36 Case #5: 4440
Author
AekdyCoin
Source
各种找规律+猜想啊!!
打表,前200的数,得到如下规律:
假设N(m)为模m的周期,则有
N(ab)=lcm(N(a),N(b)),其中gcd(a,b)=1;
N(p^k)=N(p)*p^(k-1),其中p为质数
所以转化成求N(p)的问题
又有如下猜想:
p%10==1 || p%10==9 N(p) | (p-1)
p%10==3 || p%10==7 N(p) | (2p+2)
所以爆p-1或2p+2的因子判断即可,当循环出现时必定会出现连续两个1.
各种猜想,目前无证明~~~以后有空证明再放上来。~
昨天脑残了,死活要去预处理所有质数的N(p)值,后来发现只有20组……orz
代码写的很挫,昨天改了一下午~~~
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <vector>
using namespace std;
#define MAXN 1000005
int prime[MAXN];
int p[MAXN];
int s[MAXN];
vector <int> pmo[MAXN];
int up;
int tag[MAXN];
int ttt[MAXN];
int answer[MAXN];
typedef struct
{
long long m[2][2];
}Matrix;
void Prime()
{
long long i,k;
up=0;
memset(prime,0,sizeof(prime));
for (i=2;i<=MAXN-3;i++)
{
if (prime[i]==1) continue;
k=i;
while(k*i<MAXN-2)
{
prime[i*k]=1;
k++;
}
p[up++]=i;
prime[i]=up-1;
}
}
Matrix Mul(Matrix a,Matrix b,int mod)
{
Matrix c;
int i,j,k;
for (i=0;i<2;i++)
{
for (j=0;j<2;j++)
{
c.m[i][j]=0;
for (k=0;k<2;k++)
{
c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%mod;
}
}
}
return c;
}
long long CountFib(int t,int mod)
{
Matrix a,b;
int k=t;
a.m[0][0]=a.m[0][1]=a.m[1][0]=b.m[0][0]=1;
a.m[1][1]=b.m[1][0]=b.m[0][1]=b.m[1][1]=0;
while(t)
{
if (t&1)
{
b=Mul(a,b,mod);
}
a=Mul(a,a,mod);
t>>=1;
}
return b.m[0][0];
}
int num[100][2];
int ret;
int now=0;
int Multi(int t,int n)
{
int ans=1;
while(n)
{
if (n&1) ans=ans*t;
t=t*t;
n>>=1;
}
return ans;
}
void DFS(int t,int mod,int mul)
{
int j;
if (mul>=ret) return;
if (t==now)
{
if (CountFib(mul,mod)==1 && CountFib(mul+1,mod)==1) ret=mul;
return;
}
for (j=0;j<=num[t][1];j++)
{
if (num[t][0]==2 && j==0) continue;
int k=mul*Multi(num[t][0],j);
DFS(t+1,mod,k);
}
}
int DT(int t,int mod)
{
int i;
ret=t;
now=0;
for (i=0;i<up;i++)
{
if (t%p[i]!=0) continue;
num[now][0]=p[i];
num[now][1]=0;
while(t%p[i]==0)
{
num[now][1]++;
t/=p[i];
}
now++;
if (t==1) break;
}
if (t!=1)
{
num[now][0]=t;
num[now++][1]=1;
}
DFS(0,mod,1);
return ret;
}
int Count(int t)
{
int i,k,j;
if (t==2)
{
return 3;
}
else if (t==5)
{
return 20;
}
if (t%10==1 || t%10==9) k=t-1;
if (t%10==3 || t%10==7) k=t*2+2;
return DT(k,t);
}
int fj[50][2];
int main()
{
int i,j,m,T,cnt;
long long n;
Prime();
scanf("%d",&T);
cnt=1;
while(T--)
{
scanf("%I64d",&n);
m=0;
for (i=0;i<up;i++)
{
if (n%p[i]==0)
{
fj[m][0]=p[i];
fj[m][1]=0;
while(n%p[i]==0)
{
fj[m][1]++;
n/=p[i];
}
m++;
}
if (n==1) break;
}
memset(answer,0,sizeof(answer));
int mm=0;
for (i=0;i<m;i++)
{
memset(tag,0,sizeof(tag));
if (fj[i][1]>0)
{
mm=max(prime[fj[i][0]],mm);
tag[prime[fj[i][0]]]+=fj[i][1]-1;
}
int tt=Count(fj[i][0]);
for (j=0;j<up;j++)
{
while(tt%p[j]==0)
{
tt/=p[j];
tag[j]++;
mm=max(mm,j);
}
if (tt==1) break;
}
for (j=0;j<=mm;j++)
{
answer[j]=max(tag[j],answer[j]);
}
}
long long pr=1;
for (i=0;i<=mm;i++)
{
for (j=0;j<answer[i];j++)
{
pr*=p[i];
}
}
printf("Case #%d: %I64d\n",cnt++,pr);
}
return 0;
}
解决了一个关于寻找模p下斐波那契数列周期性的数学问题,通过分析模运算的性质和质数的周期特性,找出最小周期m使得对于任意非负整数n,f(n)等于f(n+m)模p。
1105

被折叠的 条评论
为什么被折叠?



