CF1548C The Three Little Pigs

https://www.luogu.com.cn/problem/CF1548C

VP到这题的时候卡了一会

有两种做法:

可以是道生成函数入门题
实际上要求的是对于一个x,求
∑ i = 1 n ( 3 i m ) \sum_{i=1}^n\binom{3i}{m} i=1n(m3i)
这个鬼东西一看就很生成函数
可以表示为
[ x m ] ∑ i = 1 n ( 1 + x ) 3 i [x^m]\sum_{i=1}^n(1+x)^{3i} [xm]i=1n(1+x)3i
按照套路化简最后变成
( 1 + x ) 3 i + 3 − ( 1 + x ) 3 ( 1 + x ) 3 − 1 \frac{(1+x)^{3i+3}-(1+x)^3}{(1+x)^3-1} (1+x)31(1+x)3i+3(1+x)3
上面那个直接用组合数算,然后大力多项式除法即可

也可以是玄妙DP
3 i , 3 i + 1 , 3 i + 2 3i,3i+1,3i+2 3i,3i+1,3i+2分在一起,看他们之间的关系
可以设 f [ i ] [ k ] = ∑ i = 0 n − 1 ( 3 i + k x ) f[i][k]=\sum_{i=0}^{n-1}\binom{3i+k}{x} f[i][k]=i=0n1(x3i+k)
答案就是 f [ n ] [ 0 ] f[n][0] f[n][0]

通过上指标求和可以得到
f [ i ] [ 0 ] + f [ i ] [ 1 ] + f [ i ] [ 2 ] = ∑ i = 0 3 n − 1 ( i x ) = ( 3 n x + 1 ) f[i][0]+f[i][1]+f[i][2]=\sum_{i=0}^{3n-1}\binom{i}{x}=\binom{3n}{x+1} f[i][0]+f[i][1]+f[i][2]=i=03n1(xi)=(x+13n)

由组合数的转移式又可以得到
f [ i ] [ 1 ] = f [ i ] [ 0 ] + f [ i − 1 ] [ 0 ]    f [ i ] [ 2 ] = f [ i ] [ 1 ] + f [ i − 1 ] [ 1 ] f[i][1]=f[i][0]+f[i-1][0]\\ ~~ \\f[i][2]=f[i][1]+f[i-1][1] f[i][1]=f[i][0]+f[i1][0]  f[i][2]=f[i][1]+f[i1][1]
然后用这三条式子就可以解出递推式了

code(生成函数):

#include<bits/stdc++.h>
#define ll long long
#define N 3000050
#define mod 1000000007
#define int long long
using namespace std;
int qpow(int x, int y) {
    int ret = 1;
    for(; y; y >>= 1, x = 1ll * x * x % mod) if(y & 1) ret = 1ll * ret * x % mod;
    return ret;
}
int fac[N], ifac[N];
void init(int n) {
    fac[0] = 1;
    for(int i = 1; i <= n; i ++) fac[i] = 1ll * fac[i - 1] * i % mod;
    ifac[n] = qpow(fac[n], mod - 2);
    for(int i = n - 1; i >= 0; i --) ifac[i] = 1ll * ifac[i + 1] * (i + 1) % mod;
}
int C(int n, int m) {
    return 1ll * fac[n] * ifac[n - m] % mod * ifac[m] % mod;
}
int n, q;
ll a[N], f[N];
signed main() {
    scanf("%lld%lld", &n, &q);
    init(3 * n + 3);
    for(int i = 0; i <= 3 * n + 3; i ++) a[i] = C(3 * n + 3, i);
 //   for(int i = 0; i <= 3 * n + 3; i ++) printf("%lld ", a[i]); printf("\n");
    a[0] --; a[0] = (a[0] + mod) % mod; a[1] = (a[1] - 3 + mod) % mod; a[2] = (a[2] - 3 + mod) % mod, a[3] = (a[3] - 1 + mod) % mod;
    for(int i = 3 * n + 3; i >= 3; i --) {
        f[i - 3] = a[i];
        a[i - 1] = (a[i - 1] - a[i] * 3 + 10ll * mod) % mod;
        a[i - 2] = (a[i - 2] - a[i] * 3 + 10ll * mod) % mod;
    }
    while(q --) {
        int x; scanf("%lld", &x);
        printf("%lld\n", f[x]);
    }
    return 0;
}
posted @ 2021-08-31 16:45  lahlah  阅读(34)  评论(0编辑  收藏  举报