BZOJ 3028: 食物(生成函数+快速幂)

28 篇文章 1 订阅
14 篇文章 0 订阅

题面

http://www.lydsy.com/JudgeOnline/problem.php?id=3028


题解

组合问题,考虑普通型生成函数。首先写出每种食物的生成函数

承德汉堡: 1+x2+x4+...

可乐: 1+x

鸡腿: 1+x+x2

蜜桃多: x+x3+x5+...

鸡块: 1+x4+x8+...

包子: 1+x+x2+x3

土豆片炒肉: 1+x

面包: 1+x3+x6+...

将所有的生成函数乘起来,利用等比数列求和公式,忽略母函数的收敛问题而得到其闭形式(好像很厉害的样子):

11x21x21x1x31xx1x211x41x41x1x21x11x3=x1x4

现在要求这个鬼东西的第 n 项。我们有两种做法,第一种就是将其n阶求导,再结合麦克劳林公式(特殊的泰勒公式),然而这样很麻烦,很不OIer。于是用第二种方法:牛顿二项式定理,传说中的“核武器”:

(1+x)n=i=0+Cn1n+i1xi

据传说,这个公式可以将生成函数与数列机巧地联系起来,还可以求数列通项等。

于是原式的第 n 项就是求(1x)4的第 n1 项,它的系数为 C3n+2 快速幂就搞定了。

可是这样为什么是对的呢?这种构造生成函数的合理性和普适性如何才能了解一下?

首先组合只关系数量,排列还关系位置。对于组合问题,构造常生成函数,对于排列问题则需构造指数型生成函数。这里简单说说问什么组合上用常生成函数是对的。

根据我幼稚的理解,由于组合只关注数量,两个函数相乘即相当于卷积。于是所有和为 n 的组合都被卷到了n这一位,于是第 n 位保存的就是选n个的组合数的方案。写的数学一点就是 Cnmxn=ni=0AixiBnixni ,其中 m <script type="math/tex" id="MathJax-Element-2889">m</script>可以看做全部的数量。于是卷起两个普通生成函数就得到了组合数的方案了。

解决排列的生成函数的原理以后再说。


代码

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

using namespace std;

int n, ans;

int Read(){
    int x = 0;  char ch = getchar();
    while(ch < '0' || ch > '9')  ch = getchar();
    while(ch >= '0' && ch <= '9')  
        x = ((x << 3) + (x << 1) + ch - '0') % MOD, ch = getchar();
    return x;
}

int main(){

    n = Read();

    ans = n * (n+1) / 2; 

    if(n % 3 == 0)  ans = ans / 3 % MOD * (n+2) % MOD;
    if((n+1) % 3 == 0)  ans = ans / 3 % MOD * (n+2) % MOD;
    if((n+2) % 3 == 0)  ans = ans % MOD * ((n+2) / 3) % MOD;

    printf("%d\n", ans);

    return 0;
}

这里写图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值