LG P7325 [WC2021] 斐波那契

Description

众所周知,小葱同学擅长计算,尤其擅长计算组合数。但是对组合数有了充分研究的小葱同学对组合数失去了兴趣,而开始研究数列。
我们定义$F_0=a,F_1=b,F_i=(F_{i-1}+F_{i-2})mod m (i leq 2)$
现在给定 $n$ 组询问,对于每组询问请找到一个最小的整数 $p$,使得 $F_p = 0$。

Solution

可以通过打表找规律发现$F_n=bf_n+af_{n-1}$

设$d=gcd (a,b,m)$

$$bf_n+af_{n-1}equiv 0pmod miff frac{b}{d}f_n+frac{a}{d}f_{n-1}equiv 0 pmod{frac{m}{d}}$$

令$a^primeleftarrow frac{a}{d},b^primeleftarrow frac{b}{d},m^primeleftarrowfrac{m}{d},q=gcd(a',m'),p=gcd(b',m'), q'=gcd(f_n,m'), p'=gcd(f_{n-1},m')$

且因为 $gcd(a^prime,b^prime,m^prime)=1,gcd(f_n,f_{n-1},m')=1$,所以 $gcd(p,q)=1,gcd(p',q')=1$。

于是有

egin{cases}pmid b'f_n+a'f_{n-1}\qmid b'f_n+a'f_{n-1}\p'mid b'f_n+a'f_{n-1}\q'mid b'f_n+a'f_{n-1}end{cases}

考虑 $egin{cases}q|b'f_n+a'f_{n-1}\q'|b'f_n+a'f_{n-1}end{cases}$

因为$q mid b'$或$q=1$,$q' mid f_{n-1}$或$q'=1$

所以 $egin{cases}qmid f_n\q'mid aend{cases}$

egin{cases}qmid f_n\q'mid aend{cases} egin{cases}qmidgcd(f_n,m')\q'mid gcd(a',m')end{cases} egin{cases}gcd(a',m')mid gcd(f_n,m')\ gcd(f_n,m')mid gcd(a',m')end{cases} $$gcd(a',m')=gcd(f_n,m')$$

同理可证: $gcd(f_{n-1},m')=gcd(b',m')$。

egin{aligned}
&b'f_n+a'f_{n-1}equiv 0pmod {m'}\
Rightarrow & frac{b'}{p}frac{f_n}{q}+frac{a'}{q}frac{f_{n-1}}{p}equiv 0pmod{frac{m'}{pq}}\
Rightarrow & frac{f_n/q}{f_{n-1}/p}equiv -frac{a'/q}{b'/p} pmod{frac{m'}{pq}}
end{aligned}

所以枚举$m$的所有因数,在map中保存所有的$left(p,q,frac{f_n/q}{f_{n-1}/p}mod frac{m'}{pq} ight)$,求答案时查表

#include<iostream>
#include<vector>
#include<cstdio>
#include<map>
using namespace std;
int ans[100005];
long long n,m,f[200005]={0,1};
struct Ele{
    long long a,b,c;
    bool operator < (const Ele &z)const{
        if(a!=z.a)return a<z.a;
        if(b!=z.b)return b<z.b;
        return c<z.c;
    }
};
vector<Ele>ve[100005];
map<Ele,int>mp;
inline int read(){
    int w=0,f=1;
    char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
    return w*f;
}
long long gcd(long long a,long long b){return b?gcd(b,a%b):a;}
void exgcd(long long a,long long b,long long &x,long long &y){
    if(!b){x=1,y=0;return;}
    exgcd(b,a%b,x,y);
    int t=x;
    x=y,y=t-a/b*y;
}
long long inv(long long a,long long p){
    long long x=0,y=0;
    exgcd(a,p,x,y);
    return (x%p+p)%p;
}
Ele calc(long long a,long long b,long long p){
    long long d1=gcd(a,p),d2=gcd(b,p),pp=p/d1/d2;
    return (Ele){d1,d2,(a/d1)*inv(b/d2,pp)%pp};
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++){
        int a=read(),b=read();
        if(!a)ans[i]=0;
        else if(!b)ans[i]=1;
        else{
            long long temp=gcd(a,gcd(b,m));
            ve[m/temp].push_back((Ele){a/temp,b/temp,i}),ans[i]=-1;
        }
    }
    for(long long i=2;i<=m;i++)if(ve[i].size()){
        mp.clear();
        for(int j=2;j<=(i<<1);j++)f[j]=(f[j-1]+f[j-2])%i;
        for(int j=2;j<=(i<<1);j++){
            if(!f[j])break;
            Ele temp=calc(f[j],f[j-1],i);
            if(mp.find(temp)==mp.end())mp[temp]=j;
        }
        for(int j=0;j<ve[i].size();j++){
            Ele temp=calc(ve[i][j].a,i-ve[i][j].b,i);
            if(mp.find(temp)!=mp.end())ans[ve[i][j].c]=mp[temp];
        }
    }
    for(int i=1;i<=n;i++)printf("%d
",ans[i]);
    return 0;
}
[WC2021] 斐波那契
原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14400375.html