码迷,mamicode.com
首页 > 其他好文 > 详细

清北集训Day6T1(生成函数)

时间:2018-03-29 22:37:59      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:出现   ...   nbsp   ons   cout   name   比较   img   log   

技术分享图片

 

听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(生成函数)

标签:出现   ...   nbsp   ons   cout   name   比较   img   log   

原文地址:https://www.cnblogs.com/zwfymqz/p/8672528.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!