P4451 [国家集训队]整数的lqp拆分
之前看过cmd的blog,还算有点生成函数基础了,所以这题还能动。
设 \(F(x)=f_ix^i\) ,\(f_i\) 表示斐波那契数列第 \(i\) 项(\(f_0=0,f_1=1,f_i=f_{i-1}+f_{i-2}\)) ,那么答案就是
\[G(x)=\sum_{k=0} F^k(x)=\dfrac{1}{1-F(x)}
\]
这个应该很好理解,枚举用了 \(k\) 个数就可以得到上式。
斐波那契的生成函数可以用如下方法计算
\[F(x)=f_0+f_1x+f_2x^2+f_3x^3+f_4x^4+\cdots\\
xF(x)=f_0x+f_1x^2+f_2x^3+f_3x^4+\cdots\\
x^2F(x)=f_0x^2+f_1x^3+f_2x^4+\cdots\\
\]
结合 \(f_i=f_{i-1}+f_{i-2}\) 得:
\[F(x)-f_0-f_1x=xF(x)-f_0x+x^2F(x)\\
F(x)-x=xF(x)+x^2F(x)\\
(x^2+x-1)F(x)+x=0\\
F(x)=\dfrac{x}{1-x-x^2}
\]
带到最开头那个式子得到答案的生成函数
\[G(x)=\dfrac{1}{1-F(x)}\\
=\dfrac{1}{1-\dfrac{x}{1-x-x^2}}\\
=\dfrac{1-x-x^2}{1-x-x^2-x}\\
=\dfrac{1-x-x^2}{1-2x-x^2}\\
=1-\dfrac{x}{1-2x-x^2}
\]
这个封闭告诉不了我们什么东西,要化简。(跟着cmd的方法学的)
尝试因式分解分母尝试化成一堆 \(\dfrac{1}{1-qx^k}\) 相加的形式。
设 \(1-2x-x^2=0\) 的两根为 \(x_1,x_2\) (\(x_1=-1-\sqrt{2},x_2=-1+\sqrt{2}\))
有
\[\dfrac{1}{x-x_1}-\dfrac{1}{x-x_2}=\dfrac{x_1-x_2}{(x-x_1)(x-x_2)}
\]
\[G(x)=1-\dfrac{x}{(x-x_1)(x-x_2)}\\
=1-\dfrac{x}{x_1-x_2}(\dfrac{1}{x-x_1}-\dfrac{1}{x-x_2})\\
=1-\dfrac{x}{x_1-x_2}(\dfrac{1}{x_2}\dfrac{1}{1-\frac{1}{x_2}}+\dfrac{1}{x_1}\dfrac{1}{1-\frac{1}{x_1}})\\
=1-\dfrac{1}{x_1-x_2}(\sum_{i=0}\dfrac{x^{i+1}}{x_2^{i+1}}-\sum_{i=0}\dfrac{x_{i+1}}{x_1^{i+1}})
\]
提取第 \(n\) 项系数
\[[x^n]G(x)=\dfrac{1}{x_2-x_1}(\dfrac{1}{x_2^{n}}-\dfrac{1}{x_1^n})\\
=\dfrac{1}{2\sqrt{2}}((1+\sqrt{2})^{n}-(1-\sqrt{2})^{n})
\]
写个程序暴力 for
一遍,1 min
内绝对能跑出 \(\sqrt{2}\bmod 10^9+7\) ,然后快速幂算就好了。
实测 2.47s
,本地可以优化乱开,都开上会快很多。。。
你可能会好奇那个 \(1\) 哪里去了。我tm都做了三道生成函数了还在想这个问题,那个 \(1\) 是加在 \([x^0]\) 上的。所以我手动带入 \(n=3\) 发现那个式子已经等于 \(5\) 了人都傻了(样例),后来才反应过来。
读入时候根据费马小定理 \(n\bmod (mod-1)\)
艹这种题我能挂3发
两行求 \(\sqrt{2}\bmod 10^9+7\)
#define mod 1000000007
signed main(){for(int i=1;;++i)if(1ll*i*i%mod==2){cout<<i<<'\n';return 0;}}
然后偷懒 #define int long long
了。
#define int long long
#define mod 1000000007
const int is2=59713600;
inline int modread(const int&p){
int x=0;char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))x=(x*10ll+ch-'0')%p,ch=getchar();
return x;
}
inline int qpow(int n,int k){int res=1;for(;k;k>>=1,n=1ll*n*n%mod)if(k&1)res=1ll*n*res%mod;return res;}
signed main(){
int n=modread(mod-1),ans=(qpow(1+is2,n)-qpow(mod+1-is2,n)+mod)%mod*qpow(is2*2%mod,mod-2)%mod;
cout<<ans<<'\n';
}
路漫漫其修远兮,吾将上下而求索