HDU 2065 "红色病毒"问题(指数生成函数+快速幂)

题目描述

传送门

题目大意:有A,B,C,D四种字母,问组成长度为N的字符串的方案数,其中A,C只能选偶数个(可不选,N<2^64)。


题解

指数型生成函数果果题。

不知道是谁说的:组合用常生成函数,排列用指数生成函数

根据肥肥图的博客,答案就是 4n1+2n1 快速幂一下。

将每个字母取法的生成函数相乘,得到一堆:

F(x)=(1+x+x22!+x33!+...)2(1+x22!+x44!+x66!...)2

ex 的泰勒展开是 ex=+i=0xii! ex 就是 ex=+i=0(1)ixii!
所以 F(x)=e2x(ex+ex2)2=e4x+2e2x+14

到这里直接求 n 阶导就得到第n项的系数: 4n+22n4=4n1+2n1

也可以直接强拆,第 n
A(n)=14((4x)nn!+2(2x)nn!)=(4n1+2n1)xnn!

又到了感性理解其正确性的时候了:对于取 n 个的排列方案,在考虑数量的前提下,乘上了在n个位置里选 i 个给一种放,另外ni个位置则放另一种的方案数,即 Aixii!Bnixni(ni)!=AiBnin!i!(ni)!xnn! ,就是在卷积的时候乘上组合数。

换种形式表述的话,常生成函数就是在搞 Cnm=ni=0CiLCnimL ,而指数生成函数就是在搞 Anm=ni=0CinAiLAnimL

所以这两种看似很神奇的生成函数,其本质也是基于排列组合


代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#define MOD 100

using namespace std;

typedef unsigned long long ULL;

int T;
ULL N;

int Pow(int x, ULL y){
    int res = 1;
    for(; y; x = x * x % MOD, y >>= 1)
        if(y & 1)  res = res * x % MOD;
    return res;
}

int main(){

    while(~ scanf("%d", &T) && T){

        for(int i = 1; i <= T; i++){
            scanf("%llu", &N);
            printf("Case %d: %d\n", i, (Pow(4, N-1) + Pow(2, N-1)) % MOD);
        }

        puts("");
    }

    return 0;
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值