hdu3977 Evil teacher

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 ?
 

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)
 

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 .
 

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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值