洛谷P4451 [國家集訓隊]整數的lqp拆分 [生成函數]
阿新 • • 發佈:2019-02-03
mat mod 語文 inline code 時間 n) 快速 long long
我們知道\(F(x)=\frac{x}{1-x-x^2}\),所以有
\[ \begin{align*} A(x)&=\frac{1}{1-F(x)}\&=1+\frac{x}{1-2x-x^2}\&=1+\frac{1}{2\sqrt{2}}(\frac{1}{1-(1+\sqrt{2})x}-\frac{1}{1-(1-\sqrt{2})x})\&=1+\sum_n \frac{1}{2\sqrt{2}}[(1+\sqrt{2})^n-(1-\sqrt{2})^n] \end{align*} \]
所以
\[ Ans_n=\frac{(1+\sqrt{2})^n-(1-\sqrt{2})^n}{2\sqrt{2}} \]
發現題目要求\(Ans_n\pmod{1e9+7}\),枚舉可得$59713600^2 \equiv 2\pmod{1e9+7} $ ,所以\(\sqrt{2}\equiv 59713600 \pmod{1e9+7}\)
傳送門
題意簡述:語文不好不會寫,自己看吧
思路如此精妙,代碼如此簡潔,實是鍛煉思維水經驗之好題
這種題當然是一眼DP啦。
設\(dp_n\)為把\(n\)拆分後的答案。為了方便我們設\(dp_0=1\)
由題意有
\[
dp_n=[n=0]+\sum_{i=1}^n dp_{n-i}f_i
\]
按照套路,我們考慮它的生成函數\(A(x)\)
\[
\begin{align*}
A(x)&=\sum_n ([n=0]+\sum_{i=1}^n f_i dp_{n-i})x^n\&=1+\sum_{n=1}^{\infty} (\sum_{i=1}^n f_i dp_{n-i})x^n\&=1+\sum_n (\sum_{i=0}^n f_i dp_{n-i})x^n//多枚舉一點不會造成影響\&=1+A(x)F(x)
\end{align*}
\]
我們知道\(F(x)=\frac{x}{1-x-x^2}\),所以有
\[ \begin{align*} A(x)&=\frac{1}{1-F(x)}\&=1+\frac{x}{1-2x-x^2}\&=1+\frac{1}{2\sqrt{2}}(\frac{1}{1-(1+\sqrt{2})x}-\frac{1}{1-(1-\sqrt{2})x})\&=1+\sum_n \frac{1}{2\sqrt{2}}[(1+\sqrt{2})^n-(1-\sqrt{2})^n] \end{align*} \]
所以
\[ Ans_n=\frac{(1+\sqrt{2})^n-(1-\sqrt{2})^n}{2\sqrt{2}} \]
發現題目要求\(Ans_n\pmod{1e9+7}\),枚舉可得$59713600^2 \equiv 2\pmod{1e9+7} $ ,所以\(\sqrt{2}\equiv 59713600 \pmod{1e9+7}\)
於是我們在\(O(\log n)\)的時間內求得了答案!
問題來了:為什麽數據範圍只有\(10^6\)呢?我\(O(\log n)\)快速冪還沒有\(O(n)\)遞推快……
代碼:
#include<bits/stdc++.h> namespace my_std{ using namespace std; #define pii pair<int,int> #define fir first #define sec second #define MP make_pair #define rep(i,x,y) for (int i=(x);i<=(y);i++) #define drep(i,x,y) for (int i=(x);i>=(y);i--) #define go(x) for (int i=head[x];i;i=edge[i].nxt) #define sz 101010 #define mod (int)(1e9+7) typedef long long ll; template<typename T> inline void read(T& t) { t=0;char f=0,ch=getchar(); double d=0.1; while(ch>‘9‘||ch<‘0‘) f|=(ch==‘-‘),ch=getchar(); while(ch<=‘9‘&&ch>=‘0‘) t=t*10+ch-48,ch=getchar(); if(ch==‘.‘) { ch=getchar(); while(ch<=‘9‘&&ch>=‘0‘) t+=d*(ch^48),d*=0.1,ch=getchar(); } t=(f?-t:t); } template<typename T,typename... Args> inline void read(T& t,Args&... args){read(t); read(args...);} void file() { #ifndef ONLINE_JUDGE freopen("a.txt","r",stdin); #endif } // inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;} } using namespace my_std; const ll sqrt2=59713600; ll ksm(ll x,int y) { ll ret=1; for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod; return ret; } ll inv(ll x){return ksm(x,mod-2);} int n; int main() { file(); read(n); cout<<(ksm(1+sqrt2,n)-ksm(mod+1-sqrt2,n)+mod)%mod*inv(2*sqrt2)%mod; }
洛谷P4451 [國家集訓隊]整數的lqp拆分 [生成函數]