hdu 3977

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<vector>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int N = 800005; 
struct Marix 
{
    int val[2][2];
};

Marix mutli(Marix a,Marix b,ll mod) 
{
    Marix c;
    for(int i=0;i<2;i++) 
        for(int j=0;j<2;j++) {
            c.val[i][j]=0;
            for(int k=0;k<2;k++) {
                c.val[i][j]+=(a.val[i][k]*b.val[k][j]);
                c.val[i][j]%=mod;
            }
        }
        return c;
} 
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a*b/gcd(a,b);}
ll prime[N],tot=0;
void Euler_prime() {
    bool check[N];
    memset(check,0,sizeof(check));
    for(int i=2;i<=N;i++) {
        if(!check[i]) prime[++tot]=i;
        for(int j=1;j<=tot;j++) {
            if(prime[j]*i>N) break;
            check[prime[j]*i]=1;
            if(i%prime[j]==0) break;
        }
    }
} 
ll num[N],time[N],cnt=0;
void solve(ll n) 
{
    memset(time,0,sizeof(time));
    ll t=ll(sqrt(n*1.00));
    for(int i=1;prime[i]<=t;i++) {
        if(n%prime[i]==0) {
            num[++cnt]=prime[i];
            while(n%prime[i]==0) {
                time[cnt]++;
                n/=prime[i];
            }
        }
    }
    if(n>1) {
        num[++cnt]=n;
        time[cnt]++;
    }
}
ll quick_pow(ll a,ll b,ll c)
{
    ll ans=1;
    for(;b;b>>=1) {
        if(b&1) { ans*=a; ans%=c;}
        a*=a;
        a%=c;
    }
    return ans;

}
Marix I,M;
void init() 
{
    M.val[0][0]=M.val[0][1]=M.val[1][0]=1; M.val[1][1]=0;
    I.val[0][0]=I.val[1][1]=1; I.val[0][1]=I.val[1][0]=0;

}
Marix quick_Mpow(Marix a,ll k,ll mod)
{
    Marix c=I,p=a;
    for(;k;k>>=1) {
        if(k&1) c=mutli(c,p,mod);
        p=mutli(p,p,mod);
    }
    return c;
}
ll legendre(ll a,ll p) 
{
    if(quick_pow(a,(p-1)>>1,p)==1) return 1;
    else                           return -1;
}
ll fac[N],c;
void find_fac(ll n)
{
    c=0;
    ll t=(ll)(sqrt(n*1.0));
    for(int i=1;i<=t;i++) {
        if(n%i==0) {
            if(i*i==n) fac[++c]=i;
            else {
                fac[++c]=i;
                fac[++c]=n/i;
            }
        }
    } 
}
ll find_loop(ll n) 
{
    solve(n);
    ll ans=1;
    for(int i=1;i<=cnt;i++) {
        ll rec=1;
        if(num[i]==2) rec=3;
        else if(num[i]==3) rec=8;
        else if(num[i]==5) rec=20;
        else {
            if(legendre(5,num[i])==1) 
                find_fac(num[i]-1);
            else 
                find_fac(2*(num[i]+1));
        sort(fac,fac+c);

        for(int k=1;k<=c;k++) {
            Marix a=quick_Mpow(M,fac[k]-1,num[i]);
            ll x=(a.val[0][0]%num[i]+a.val[0][1]%num[i])%num[i];
            ll y=(a.val[1][0]%num[i]+a.val[1][1]%num[i])%num[i];
            if(x==1&&y==0) {
                rec=fac[k];
                break;
            }
        }
        }
        for(int k=1;k<time[i];k++) 
            rec*=num[i];
        ans=lcm(ans,rec);
    }
        return ans;
}
int main() 
{
    ll n,T;
    init();
    Euler_prime();
    ll kase=0;
    cin>>T;
    while(T--) 
    {   
        cin>>n;
        c=0;
        cnt=0;
        printf("Case #%lld: %lld\n",++kase,find_loop(n));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值