LG P7325 [WC2021] 斐波那契

Description

众所周知,小葱同学擅长计算,尤其擅长计算组合数。但是对组合数有了充分研究的小葱同学对组合数失去了兴趣,而开始研究数列。
我们定义$F_0=a,F_1=b,F_i=(F_{i-1}+F_{i-2})\bmod 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 0\pmod m\iff \frac{b}{d}f_n+\frac{a}{d}f_{n-1}\equiv 0 \pmod{\frac{m}{d}}$$

令$a^\prime\leftarrow \frac{a}{d},b^\prime\leftarrow \frac{b}{d},m^\prime\leftarrow\frac{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$。

于是有

\begin{cases}p\mid b'f_n+a'f_{n-1}\\q\mid 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}

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

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

所以 $\begin{cases}q\mid f_n\\q'\mid a\end{cases}$

\begin{cases}q\mid f_n\\q'\mid a\end{cases} \begin{cases}q\mid\gcd(f_n,m')\\q'\mid \gcd(a',m')\end{cases} \begin{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')$。

\begin{aligned}
&b'f_n+a'f_{n-1}\equiv 0\pmod {m'}\\
\Rightarrow & \frac{b'}{p}\frac{f_n}{q}+\frac{a'}{q}\frac{f_{n-1}}{p}\equiv 0\pmod{\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}\right)$,求答案时查表

#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\n",ans[i]);
    return 0;
}
[WC2021] 斐波那契

 

posted @ 2021-02-13 17:18  QDK_Storm  阅读(176)  评论(0编辑  收藏  举报