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)$,求答案时查表
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }