1 条题解
-
0
自动搬运
来自洛谷,原作者为

Soulist
再见了搬运于
2025-08-24 22:11:17,当前版本为作者最后更新于2019-12-01 10:46:05,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
这篇题解对于许多题解打表/一言概括得到的结论进行了充分的证明我们将序列看作一个
考虑计算前缀和,众所周知,只需要拿它乘以
根据一些等比数列求和的芝士我们知道
置于求它的差分,则拿和卷起来即可
好了那么维前缀和呢?
维差分呢?
好了然后求个,乘个,取个这道题就做完了
但是非常不幸的是这样会非常难写而且我已经不会求和了(不要问我怎么清,我也不会清)
于是我们还是用点生成函数的技巧吧
首先是差分,它非常好做:
二项式定理强行打开使我们可以知道:
好的这道题真是见了鬼了这么大搞什么。。。
不过这道题要用连续的组合数然而它可以递推
$\dbinom{k}{0}=1,\dbinom{k}{i}=\dbinom{k}{i-1}\times\dfrac{k-i+1}{i}$
然后大概是可以直接取模的。。。
好了接下来是:
这个有点麻烦,需要借助广义二项式定理:
我们把它看作
根据广义二项式定理它等价于:
这个式子看上去挺对的。。。毕竟当的时候不过现在我们不能用阶乘来定义组合数了,于是我们需要把它改成下降幂的形式:
注:
好的我们来看下代入进去是什么样的:
$$(1-x)^{-k}=\sum_{i=0}^{\infty}(-1)^i\dfrac{(-k)^{\underline{i}}}{i!}x^i $$$$(1-x)^{-k}=\sum_{i=0}^{\infty}(-1)^{2i}\dfrac{(k+i-1)^{\underline{i}}}{i!}x^i $$所以我们知道:
$$(1-x)^{-k}=\sum_{i=0}^{\infty}\dbinom{k+i-1}{i}x^i $$好了于是对于差分我们只需要拿和卷起来即可
对于前缀和我们只需要拿和卷起来即可
当然这个什么也可以递推,因为它是,要递推的话也很简单,每次乘一个即可
然后模数还是模数。。。
实际上这篇题解是在做一些特别蠢的证明。。。#include<bits/stdc++.h> using namespace std ; #define rep( i, s, t ) for( register int i = s; i <= t; ++ i ) #define re register #define int long long const int P = 1004535809 ; const int Gi = 334845270 ; const int G = 3 ; int gi() { char cc = getchar() ; int cn = 0, flus = 1 ; while( cc < '0' || cc > '9' ) { if( cc == '-' ) flus = - flus ; cc = getchar() ; } while( cc >= '0' && cc <= '9' ) cn = ( cn * 10 + cc - '0' ) % P, cc = getchar() ; return cn * flus ; } const int N = 1e5 + 5 ; int n, m, A[N << 2], B[N << 2], limit, L, Inv, R[N << 2] ; int fpow( int x, int k ) { int ans = 1, base = x ; while( k ) { if( k & 1 ) ans = ( ans * base ) % P ; base = ( base * base ) % P, k >>= 1 ; } return ans ; } void init( int x ) { limit = 1, L = 0 ; while( limit <= x ) limit <<= 1, ++ L ; rep( i, 0, limit ) R[i] = ( R[i >> 1] >> 1 ) | ( ( i & 1 ) << ( L - 1 ) ) ; Inv = fpow( limit, P - 2 ) ; } void NTT( int *a, int type ) { for( re int i = 0; i < limit; ++ i ) if( R[i] > i ) swap( a[i], a[R[i]] ) ; for( re int k = 1; k < limit; k <<= 1 ) { int d = fpow( ( type == 1 ) ? G : Gi, ( P - 1 ) / ( k << 1 ) ) ; for( re int i = 0; i < limit; i += ( k << 1 ) ) for( re int j = i, g = 1 ; j < i + k; ++ j, g = ( g * d ) % P ) { int Nx = a[j], Ny = ( a[j + k] * g ) % P ; a[j] = ( Nx + Ny ) % P, a[j + k] = ( Nx - Ny + P ) % P ; } } if( type != 1 ) rep( i, 0, limit ) a[i] = a[i] * Inv % P ; } signed main() { n = gi(), m = gi() ; int type = gi() ; rep( i, 1, n ) A[i - 1] = gi() ; B[0] = 1 ; if( type == 0 ) rep( i, 1, n ) B[i] = B[i - 1] * ( m + i - 1 ) % P * fpow( i, P - 2 ) % P ; if( type == 1 ) rep( i, 1, n ) B[i] = ( -B[i - 1] * ( m - i + 1 + P ) % P * fpow( i, P - 2 ) % P + P ) % P ; init( n + n ), NTT( A, 1 ), NTT( B, 1 ) ; rep( i, 0, limit ) A[i] = A[i] * B[i] % P ; NTT( A, -1 ) ; rep( i, 1, n ) printf("%lld ", A[i - 1] ) ; return 0 ; }
- 1
信息
- ID
- 4454
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者