Codeforces 717A Festival Organization(组合数学:斯特林数+Fibonacci数列+推公式)

Codeforces 717A Festival Organization(组合数学:斯特林数+Fibonacci数列+推公式)

牛逼题。。。。。推公式非常的爽。。。虽然我是看了别人的博客才推出来的。。。

0.1 斯特林数

下面要用到的是带符号的第一类斯特林数。

\(x^{n\downarrow}=\prod_{i=0}^{n-1}(x-i)=\sum_{k=0}^ns(n,k)x^k\)

有递推公式\(s(n,m)=s(n-1,m-1)-(n-1)*s(n-1,m)\)

0.2 斐波那契数列的通项公式

\(f_i=\frac{1}{\sqrt5}[(\frac{1+\sqrt5}{2})^i-(\frac{1-\sqrt5}{2})^i]\)

1 求出长度为\(n\)的合法0/1序列数

先考虑dp做法,\(a_{i,0}\)表长度为\(i\),结尾为\(1\)的方案数,\(a_{i,1}\)同理。

很明显有\(a_{0,0}=a_{0,1}=1,a_{i,0}=a_{i-1,1},a_{i,1}=a_{i-1,0}+a_{i-1,1}\)

数学归纳法很轻松就能证出\(a_{i,0}=F_{i},a_{i,1}=F_{i+1}\),则长度为\(n\)的方案数为\(F_{i+2}\),其中\(F_i\)表斐波那契数列的第\(i\)项\((F_1=F_2=1)\)

2 \(Ans,S_n\)

\(Ans=\sum_{i=l}^r C_{F_{i+2}}^k\)

记\(S_n=\sum_{i=1}^nC_{F_{i+2}}^k=\sum_{i=3}^{n+2}C_{F_i}^k\)

则有\(Ans=S_r-S_{l-1}\)

3 化简

\(S_n\)

\(=\frac{1}{k!}\sum_{i=3}^{n+2}\prod_{j=0}^{k-1}(F_i-j)\)

\(=\frac{1}{k!}\sum_{i=3}^{n+2}\sum_{j=0}^ks(k,j)F_i^j\)

\(=\frac{1}{k!}\sum_{j=0}^k\sum_{i=3}^{n+2}s(k,j)F_i^j\)

\(=\frac{1}{k!}\sum_{j=0}^ks(k,j)\sum_{i=3}^{n+2}F_i^j\)

\(=\frac{1}{k!}\sum_{j=0}^ks(k,j)\sum_{i=3}^{n+2}(\frac{1}{\sqrt5}[a^i-b^i])^j\) 其中\(a=\frac{1+\sqrt5}{2},b=\frac{1-\sqrt5}{2}\)

\(=\frac{1}{k!}\sum_{j=0}^ks(k,j)\sum_{i=3}^{n+2}\sum_{p=0}^j(\frac{1}{5}\sqrt5)^jC_j^pa^{ip}(-1)^{j-p}b^{i(j-p)}\)

\(=\frac{1}{k!}\sum_{j=0}^ks(k,j)\sum_{p=0}^j(\frac{1}{5}\sqrt5)^jC_j^p(-1)^{j-p}\sum_{i=3}^{n+2}a^{ip}b^{i(j-p)}\)

\(=\frac{1}{k!}\sum_{j=0}^ks(k,j)\sum_{p=0}^j(\frac{1}{5}\sqrt5)^jC_j^p(-1)^{j-p}\sum_{i=3}^{n+2}(a^pb^{j-p})^i\)

\(=\frac{1}{k!}\sum_{j=0}^ks(k,j)\sum_{p=0}^j(\frac{1}{5}\sqrt5)^jC_j^p(-1^{j-p})*T(j,p)\)

其中,令\(q(j,p)=a^pb^{j-p}\)

\[T(j,p)=\begin{cases}
n & q(j,p)=1 \\frac{q^3(j,p)(1-q^n(j,p))}{1-q(j,p)} & q(j,p)\not=1
\end{cases}\]

枚举\(j,p\)就能得到答案了。

4 代码

#include <bits/stdc++.h>
#define pii pair<long long,long long>
#define LL long long
#define x first
#define y second
#define MAXN 7000
using namespace std;
const LL mod = 1000000007;
LL k, L, R;
LL qp(LL a, LL b)
{
    LL ret = 1;
    while (b)
    {
        if (b & 1)
            ret = ret * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ret;
}

LL Inv[208];
LL inv(LL a)
{
    if (a > 200)
        return qp(a, mod - 2);
    else if (!Inv[a])
        return Inv[a] = qp(a, mod - 2);
    else
        return Inv[a];
}

LL CC[208][208];
LL S[208][208];
void init()
{
    CC[0][0] = 1;
    for (LL i = 1; i <= 200; ++i)
    {
        CC[i][0] = 1;
        for (LL j = 1; j <= i; ++j)
        {
            CC[i][j] = CC[i][j - 1] * inv(j) % mod * (i - j + 1) % mod;
        }
    }
    S[0][0] = 1;
    for (LL i = 1; i <= 200; ++i)
    {
        S[i][0] = 0;
        for (LL j = 1; j < i; ++j)
        {
            S[i][j] = ((S[i - 1][j - 1] - (i - 1) * S[i - 1][j] % mod) % mod + mod) % mod;
        }
        S[i][i] = 1;
    }
}

struct tls
{
    LL a, b;
    tls(){}
    tls(LL _a, LL _b){a = (_a % mod + mod) % mod; b = (_b % mod + mod) % mod;}
    tls operator+(const tls& t) const
    {
        return tls((a + t.a) % mod, (b + t.b) % mod);
    }
    tls operator-(const tls& t) const
    {
        return tls((a - t.a + mod) % mod, (b - t.b + mod) % mod);
    }
    tls operator*(const tls& t) const
    {
        return tls((a*t.a%mod + 5*b%mod*t.b%mod) % mod, (a*t.b%mod + b*t.a%mod) % mod);
    }
    tls operator/(const tls& t) const
    {
        LL r = inv((t.a*t.a%mod - 5*t.b%mod*t.b%mod + mod) % mod);
        if ((t.a*t.a%mod - 5*t.b%mod*t.b%mod + mod) % mod == 0)
            throw;
        return tls(r * (((a*t.a%mod) - (b*t.b%mod*5%mod) + mod) % mod) % mod, (r * (((t.a*b%mod) - (a*t.b%mod) + mod) % mod) % mod));
    }
};

tls qp(tls a, LL b)
{
    tls ret(1, 0);
    while (b)
    {
        if (b & 1)
            ret = ret * a;
        a = a * a;
        b >>= 1;
    }
    return ret;
}

ostream& operator<<(ostream& out, tls p)
{
    out << p.a << "+" << p.b << "sqrt(5)";
    return out;
}

LL gao(LL n, LL k)
{
    tls a(inv(2)%mod, inv(2)%mod), b(inv(2)%mod,(mod-inv(2)%mod)%mod);
    tls ret(0, 0);
    for (LL j = 0; j <= k; ++j)
    {
        tls tot(0, 0);
        for (LL p = 0; p <= j; ++p)
        {
            tls temp(1, 0);
            tls q = qp(a/b, p) * qp(b, j);
            if (q.a == 1 && q.b == 0)
            {
                temp = temp * tls(n, 0);
            }
            else
            {
                temp = temp * qp(q, 3) * (tls(1, 0) - qp(q, n));
                temp = temp / (tls(1, 0) - q);
            }
            temp = temp * tls(qp(mod - 1, j - p), 0) * tls(CC[j][p], 0);

            tot = tot + temp;
        }
        tot = tot * tls(S[k][j], 0) * qp(tls(0, inv(5)), j);
        ret = ret + tot;
    }
    for (LL i = 1; i <= k; ++i)
    {
        ret = ret * tls(inv(i), 0);
    }
    return ret.a;
}

int main()
{
    /*cout << inv(25) << endl;
    cout << qp(tls(0, inv(5)), 4) << endl;*/
    init();
    cin >> k >> L >> R;
    cout << (gao(R, k) - gao(L - 1, k) + mod) % mod << endl;
    return 0;
}

原文地址:https://www.cnblogs.com/zhugezy/p/10969998.html

时间: 2024-11-05 13:45:40

Codeforces 717A Festival Organization(组合数学:斯特林数+Fibonacci数列+推公式)的相关文章

HDU 4045 Machine scheduling (组合数学-斯特林数,组合数学-排列组合)

Machine scheduling Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1000    Accepted Submission(s): 363 Problem Description A Baidu's engineer needs to analyze and process large amount of data o

HDU 4372 Count the Buildings(组合数学-斯特林数,组合数学-排列组合)

Count the Buildings Problem Description There are N buildings standing in a straight line in the City, numbered from 1 to N. The heights of all the buildings are distinct and between 1 and N. You can see F buildings when you standing in front of the

HDU 3240 Counting Binary Trees(组合数学-斯特林数,数论-整数快速幂,数论-求逆元)

Counting Binary Trees Problem Description There are 5 distinct binary trees of 3 nodes: Let T(n) be the number of distinct non-empty binary trees of no more than n nodes, your task is to calculate T(n) mod m. Input The input contains at most 10 test

【BZOJ 4555】[Tjoi2016&amp;Heoi2016]求和 NTT+第二类斯特林数

用到第二类斯特林数的性质,做法好像很多,我打的是直接ntt,由第二类斯特林数的容斥公式可以推出,我们可以对于每一个i,来一次ntt求出他与所有j组成的第二类斯特林数的值,这个时候我们是O(n^2logn)的,还不如暴力,但是我们发现,对于刚刚提到的容斥的式子,将其化为卷积形式后,其一边的每一项对于每一个i都相同,另一边的每一项是对于所有的i形成一个n项的等比数列,这样我们可以把成等比数列的一边求和,用固定的一边去卷他们的和,这时候的答案的每一项就是所有的i的这一项的和,然后我们再O(n)乘上阶乘

卡特兰数 斯特林数

卡特兰数\(C_{2n}^n - C_{2n}^{n-1}\) 还有常用的递推: int main() { scanf("%d", &n); f[0] = 1, f[1] = 1; for(int i=2; i<=n; i++) { for(int j=0; j<i; j++) { f[i] += f[j] * f[i-j-1]; } } printf("%d", f[n]); return 0; } 貌似很多题都是第0项为1,第一项为1,第二项

【2019雅礼集训】【第一类斯特林数】【NTT&amp;多项式】permutation

目录 题意 输入格式 输出格式 思路: 代码 题意 找有多少个长度为n的排列,使得从左往右数,有a个元素比之前的所有数字都大,从右往左数,有b个元素比之后的所有数字都大. n<=2*10^5,a,b<=n 输入格式 输入三个整数n,a,b. 输出格式 输出一个整数,表示答案. 思路: 这道题是真的神啊... 首先,根据官方题解的思路,首先有一个n^2的DP: 定义dp[i][j]表示一个长度为i的排列,从前往后数一共有j个数字大于所有排在它前面的数字. 首先有转移式: \[dp[i][j]=d

CF717A Festival Organization(第一类斯特林数,斐波那契数列)

题目大意:求 $\sum\limits_{n=l}^{r}\dbinom{f_n}{k}\bmod 10^9+7$.其中 $f_n$ 是长度为 $n$ 的 $01$ 序列中,没有连续两个或超过两个 $0$ 的个数. $1\le k\le 200,1\le l\le r\le 10^{18}$. 先考虑如何求 $f_n$. 令 $g[i][j]$ 表示长度为 $i$,结尾是 $j$ 的序列个数. $$g[i][0]=g[i-1][1]$$ $$g[i][1]=g[i-1][0]+g[i-1][1]

【BZOJ4555】求和(第二类斯特林数,组合数学,NTT)

[BZOJ4555]求和(第二类斯特林数,组合数学,NTT) 题面 BZOJ 题解 推推柿子 \[\sum_{i=0}^n\sum_{j=0}^iS(i,j)·j!·2^j\] \[=\sum_{i=0}^n\sum_{j=0}^nS(i,j)·j!·2^j\] \[=\sum_{i=0}^n\sum_{j=0}^nj!·2^j(\frac{1}{j!}\sum_{k=0}^j(-1)^k·C_j^k·(j-k)^i)\] \[=\sum_{j=0}^n2^j\sum_{k=0}^j(-1)^k

【BZOJ5093】图的价值(第二类斯特林数,组合数学,NTT)

[BZOJ5093]图的价值(第二类斯特林数,组合数学,NTT) 题面 BZOJ 题解 单独考虑每一个点的贡献: 因为不知道它连了几条边,所以枚举一下 \[\sum_{i=0}^{n-1}C_{n-1}^i·i^k·2^{\frac{n(n-1)}{2}}\] 因为有\(n\)个点,所以还要乘以一个\(n\) 所以,我们真正要求的就是: \[\sum_{i=0}^{n-1}C_{n-1}^i·i^k\] 怎么做? 看到了\(i^k\)想到了第二类斯特林数 \[m^n=\sum_{i=0}^{m}