1. 程式人生 > >清北集訓Day6T1(生成函數)

清北集訓Day6T1(生成函數)

main 答案 amp define ons .... efi () 方案

技術分享圖片

聽rqy說可以用生成函數做,感覺比較有意思

我們考慮在DP轉移的時候,

$5,7,9$這三個數是沒有限制的

因此他們出現的次數用01串表示的話就是$1111111111111111......$

$3,5$這兩個數只能出現偶數次且必須出現

因此他們出現的次數用01串表示的話是$0010101010101010101....$

因為是組合計數問題,我們考慮用指數型生成函數來搞

對於第一個肯定就是$e^x$

對於第二個,我們首先用$\frac{e^x+e^{-x}}{2}$構造出$1010101010.....$

然後再減個$1$就好了

這樣的話我們不難得到答案的方案實際就是

$\left( e^{x}\right) ^{3}\left( \dfrac {e^{x}+e^{-x}}{2}-1\right) ^{2}$

然後暴力推推推就可以得到

$\dfrac {1}{4}e^{5x}+\dfrac {1}{4}e+\dfrac {6}{4}e^{3x}-\dfrac {4}{4}e^{4x}-\dfrac {4}{4}e^{2x}$

然後快速冪搞一搞就好了

生成函數好神奇QWQ。。。

#include<cstdio>
#include<iostream>
#define int long long 
using namespace std;
const int MAXN=1e6+10;
const int mod=1e9+7;
int a[MAXN]={0
,5,1,3,4,2}; int k[MAXN]={0,1,1,6,-4,-4}; int fastpow(int a,int p) { int base=1; while(p) { if(p&1) base=(base*a)%mod; a=(a*a)%mod; p>>=1; } return base%mod; } main() { int N,ans=0; cin>>N; for(int i=1;i<=5;i++) ans
=( ans + fastpow(a[i], N) * k[i] ) %mod; cout<<( ans * ( (mod + 1) / 4 ) %mod + mod ) %mod; return 0; }

清北集訓Day6T1(生成函數)