组合数学练习题——Chemist

Posted nopartyfoucaodong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了组合数学练习题——Chemist相关的知识,希望对你有一定的参考价值。

题意:

在一个 n 维无限空间中,一开始原点处有一个细胞。细胞每秒都会增殖,每个原有细胞都会消亡,在与它曼哈顿距离恰为 1的所有位置都会新增一个细胞。求 T 秒后,原点处会有多少细胞,答案 mod1000000007。

共有Q组询问,每组询问给你n和T。Q ≤ 20000,n ≤ 100,T ≤ 200。

分析:

对于每次扩散,都会扩散到原细胞周围距离为1的一圈,由于最初每一个细胞都会从原点出发,我们可以考虑成原点的细胞的分身经过长途跋涉,每次可以朝着一个维度前进,也可以朝着一个维度后退,只要T秒后他可以回到原点,那么他对答案的贡献就加一。这样问题就等价于求有多少回到原点的长度为T的路径(从原点出发再回到原点看做一条路径)。

由于维度什么的实在是太抽象了,因此我们可以把每一维分开考虑,设 f[i][j] 表示用了i个维度,长度为2j的回到原点路径条数。设第i+1维走了2k步,那么在这2k步种,需要有k步向前走,k步向后走才能回到原点,方案数为C(k,2k)。此时走了2(j+k)步,对于这2(j+k)步,先走哪一步后走哪一步本质上是无所谓的,但是算作不同的方案,因此答案还要乘上C(2k,2(j+k)),这样就可以得到递推方程:

f[i+1][j+k]=f[i][j]C(k,2k)C(2k,2(j+k))

由于n,T都不大,所以可以预处理出f[i][j],O(1)回答每次询问。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int Q,n,t;
ll f[110][210],c[210][210];
void prework()
{
    for(int i=0;i<=200;i++)
     c[i][0]=1;
    for(int i=1;i<=200;i++)
     for(int j=1;j<=200;j++)
      c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
    f[0][0]=1;
    for(int i=0;i<=100;i++)
     for(int j=0;2*j<=200;j++)
      for(int k=0;2*(j+k)<=200;k++)
      {
        f[i+1][j+k]=(f[i+1][j+k]+(c[2*k][k]*c[2*(j+k)][2*k])%mod*f[i][j]%mod)%mod;
      }
}
int main()
{
    prework();
    cin>>Q;
    for(int i=1;i<=Q;i++){
        cin>>n>>t;
        if(t&1==1)cout<<‘0‘<<endl;
        else cout<<f[n][t/2]<<endl;
    }
    return 0;
}

以上是关于组合数学练习题——Chemist的主要内容,如果未能解决你的问题,请参考以下文章

拓扑排序复习——Chemist

莫比乌斯反演总结——Chemist

Relay.js 没有正确解析组合片段

Python练习册 第 0013 题: 用 Python 写一个爬图片的程序,爬 这个链接里的日本妹子图片 :-),(http://tieba.baidu.com/p/2166231880)(代码片段

JavaScript 代码片段

spring练习,在Eclipse搭建的Spring开发环境中,使用set注入方式,实现对象的依赖关系,通过ClassPathXmlApplicationContext实体类获取Bean对象(代码片段