Codechef:Fibonacci Number/FN——求通项+二次剩余+bsgs

题意

定义 $F_n$ 为

$$F_n = \left\{\begin{matrix}
0, n=0\\
1, n=1 \\
F_{n-1} + F_{n-2}, n > 1
\end{matrix}\right.$$

现给你一个素数 $p$ 和一个非负整数 $C$,你需要最小的非负整数 $n$,使得 $F_n \equiv C (mod \ p)$.

分析

因为题目保证 $p \ mod \ 10$ 是一个完全平方数,也就是说 $p \ mod \ 5$ 等于1或-1,即5是模$p$ 的二次剩余(据说)。

求出通项,用Cipolla求出5的二次剩余,记为 $c$,并记 $p = \frac{1+c}{2}$,

通项变成

$${1\over c}\left(p^n-(-1)^n{1\over p^n}\right)\equiv a\pmod{P}$$

解得

$$p^n\equiv {ac\pm \sqrt{ac+4(-1)^n}\over 2}$$

然后枚举一下 $n$ 的奇偶性,再用BSGS求出 $n$就可以了。

//我原来的模板好像有问题,这里贴大佬的模板

//minamoto
#include<bits/stdc++.h>
#define R register
#define inf 0x7fffffff
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
    R int res,f=1;R char ch;
    while((ch=getc())>‘9‘||ch<‘0‘)(ch==‘-‘)&&(f=-1);
    for(res=ch-‘0‘;(ch=getc())>=‘0‘&&ch<=‘9‘;res=res*10+ch-‘0‘);
    return res*f;
}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(R int x){
    if(C>1<<20)Ot();if(x<0)sr[++C]=‘-‘,x=-x;
    while(z[++Z]=x%10+48,x/=10);
    while(sr[++C]=z[Z],--Z);sr[++C]=‘\n‘;
}
int P;
inline int add(R int x,R int y){return 0ll+x+y>=P?0ll+x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
    R int res=1;
    for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
    return res;
}
int w,a;
struct cp{
    int x,y;
    inline cp(R int _x,R int _y):x(_x),y(_y){}
    inline cp operator *(const cp &b)const{
        return cp(add(mul(x,b.x),mul(w,mul(y,b.y))),add(mul(x,b.y),mul(y,b.x)));
    }
};
int ksm(R cp x,R int y){
    R cp res(1,0);
    for(;y;y>>=1,x=x*x)if(y&1)res=res*x;
    return res.x;
}
int Sqrt(int x){
    if(!x)return 0;
    if(ksm(x,(P-1)>>1)==P-1)return -1;
    while(true){
        a=mul(rand(),rand()),w=dec(mul(a,a),x);
        if(ksm(w,(P-1)>>1)==P-1)return ksm(cp(a,1),(P+1)>>1);
    }
}
const int N=262144;
struct Hash{
    struct eg{int v,nx,w;}e[N];int head[N],tot;
    inline void clr(){memset(head,0,sizeof(head)),tot=0;}
    inline void add(R int v,R int w){e[++tot]={v,head[v&262143],w},head[v&262143]=tot;}
    int query(int x){
        go(x&262143)if(v==x)return e[i].w;
        return -1;
    }
}mp[2];
int bsgs(int x,int v,int sgn){
    int m=sqrt(P)+1;mp[0].clr(),mp[1].clr();
    for(R int i=1,res=mul(v,x);i<=m;++i,res=mul(res,x))mp[i&1].add(res,i);
    for(R int i=1,tmp=ksm(x,m),res=tmp;i<=m;++i,res=mul(res,tmp))
        if(mp[(i*m)&1^sgn].query(res)!=-1)return i*m-mp[(i*m)&1^sgn].query(res);
    return inf;
}
int c,s,p,inv2,res,rt;
int main(){
    srand(time(NULL));
//  freopen("testdata.in","r",stdin);
    for(int T=read();T;--T){
        c=read(),P=read(),s=Sqrt(5),inv2=(P+1)>>1,p=mul(s+1,inv2),c=mul(c,s);
        res=inf;
        rt=Sqrt((1ll*c*c+4)%P);
        if(rt!=-1){
            cmin(res,bsgs(p,mul(add(c,rt),inv2),0)),
            cmin(res,bsgs(p,mul(dec(c,rt),inv2),0));
        }
        rt=Sqrt((1ll*c*c+P-4)%P);
        if(rt!=-1){
            cmin(res,bsgs(p,mul(add(c,rt),inv2),1)),
            cmin(res,bsgs(p,mul(dec(c,rt),inv2),1));
        }
        printf("%d\n",res==inf?-1:res);
    }
    return 0;
}

参考链接:https://www.cnblogs.com/bztMinamoto/p/10664967.html

原文地址:https://www.cnblogs.com/lfri/p/11515048.html

时间: 2024-10-01 10:08:55

Codechef:Fibonacci Number/FN——求通项+二次剩余+bsgs的相关文章

hdu 3509 Buge&#39;s Fibonacci Number Problem

点击此处即可传送 hdu 3509 题目大意:F1 = f1, F2 = f2;; F(n) = a*F(n-1) + b*F(n-2); S(n) = F1^k + F2^k +-.+Fn^k; 求S(n) mod m; 解题思路: 1:首先一个难题就是怎么判断矩阵的维数(矩阵的维数是个变量) 解决方法:开一个比较大的数组,然后再用一个公有变量记一下就行了,具体详见代码: 2:k次方,找规律: 具体上代码吧: /* 2015 - 8 - 16 晚上 Author: ITAK 今日的我要超越昨日

Fibonacci number

https://github.com/Premiumlab/Python-for-Algorithms--Data-Structures--and-Interviews/blob/master/Mock%20Interviews/Large%20Search%20Engine%20Company%20/Search%20Engine%20Company%20-%20Interview%20Problems%20-%20SOLUTIONS/Phone%20Screen.ipynb Phone Sc

projecteuler----&gt;problem=25----1000-digit Fibonacci number

问题描述: The Fibonacci sequence is defined by the recurrence relation: Fn = Fn1 + Fn2, where F1 = 1 and F2 = 1. Hence the first 12 terms will be: F1 = 1 F2 = 1 F3 = 2 F4 = 3 F5 = 5 F6 = 8 F7 = 13 F8 = 21 F9 = 34 F10 = 55 F11 = 89 F12 = 144 The 12th term

【HDOJ】3509 Buge&#39;s Fibonacci Number Problem

快速矩阵幂,系数矩阵由多个二项分布组成.第1列是(0,(a+b)^k)第2列是(0,(a+b)^(k-1),0)第3列是(0,(a+b)^(k-2),0,0)以此类推. 1 /* 3509 */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #include <queue> 6 #include <set> 7 #include <stack> 8 #incl

(斐波那契总结)Write a method to generate the nth Fibonacci number (CC150 8.1)

根据CC150的解决方式和Introduction to Java programming总结: 使用了两种方式,递归和迭代 CC150提供的代码比较简洁,不过某些细节需要分析. 现在直接运行代码,输入n(其中用number代替,以免和方法中的n混淆)的值,可以得出斐波那契数. 代码如下: /* CC150 8.1 Write a method to generate the nth Fibonacci number Author : Mengyang Rao note : Use two me

Buge&#39;s Fibonacci Number Problem

Buge's Fibonacci Number Problem Description snowingsea is having Buge’s discrete mathematics lesson, Buge is now talking about the Fibonacci Number. As a bright student, snowingsea, of course, takes it as a piece of cake. He feels boring and soon com

特征根法求通项+广义Fibonacci数列找循环节 - HDU 5451 Best Solver

Best Solver Problem's Link Mean: 给出x和M,求:(5+2√6)^(1+2x)的值.x<2^32,M<=46337. analyse: 这题需要用到高中的数学知识点:特征根法求递推数列通项公式. 方法是这样的: 对于这题的解法: 记λ1=5+2√6,λ2=5-2√6,则λ1λ2=1,λ1+λ2=10 根据韦达定理可以推导出:λ1,λ2的特征方程为 x^2-10x+1=0 再使用该特征方程反向推导出递推公式为:a[n]=10*a[n-1]-a[n-2] 再由特征根

Project Euler:Problem 25 1000-digit Fibonacci number

The Fibonacci sequence is defined by the recurrence relation: Fn = Fn?1 + Fn?2, where F1 = 1 and F2 = 1. Hence the first 12 terms will be: F1 = 1 F2 = 1 F3 = 2 F4 = 3 F5 = 5 F6 = 8 F7 = 13 F8 = 21 F9 = 34 F10 = 55 F11 = 89 F12 = 144 The 12th term, F1

hdu 1394 Minimum Inversion Number 归并求逆序数

Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 12107    Accepted Submission(s): 7388 Problem Description The inversion number of a given number sequence a1, a2, ..., a