HDU - 6397 (2018 Multi-University Training Contest 8)

https://vjudge.net/problem/HDU-6397

比赛的时推了半天不知道为什么没有推导出来,很难受,只想到了O((k/n)^2)的算法,相当的难受啊

看了dls的讲解,顺便学习了一波推生成函数的方法

题意很简单,就是将k分成n个数,每个数的范围是[0,n-1],问一共有多少中方法

 

我们先不看k,只看n和m

当n=2时

     0  1   2   3   4   5   6   7   8  9 10 11...

0   1

1   1  1

2   1  2   1

3   1  3   3   1

4   1  4   6   4   1

5   1  5  10  10   5   1

6   1  6  15  20  15   6   1

7   1  7  21  35  35  21   7   1

8   1  8  28  56  70  56  28   8   1

9   1  9  36  84 126 126  84  36   9  1

10  1 10  45 120 210 252 210 120  45 10  1

11  1 11  55 165 330 462 462 330 165 55 11  1

很显然就是杨辉三角,直接二项式定理就可以了

当n=3是,也是类似的

     0   1   2   3   4    5    6      7      8     9   10  11  12

0:  1

1:  1   1   1

2:  1   2   3    2    1

3:  1   3   6    7    6   3    1

4:  1   4  10  16  19  16  10   4      1

5:  1   5  15  30  45  51  45   30   15    5   1

6:  1   6  21  50  90 126 141 126  90  50 21  6  1

 

生成公式:

(1+x+x^{2}+...+x^{n}) ^{m}

这个公式就是就可以表示第m行的结果,对应的系数就是展开式中x^i的系数,所以我们只需要求生成公式中x^k的系数即可。

那么我们就得对公式化简

(1+x+x^{2}+...+x^{n-1}) ^{m} \\ =(\frac{1-x^{n}}{1-x}) ^{m} \\ =(1-x^{n})^{m} (1-x) ^{-m}

根据泰勒展开:

可得

(1-x) ^{-m}=\sum_{i=0}^{\infty}C_{m+i-1} ^{m-1} x^{i}

所以

(1+x+x^{2}+...+x^{n-1}) ^{m} \\ =(\frac{1-x^{n}}{1-x}) ^{m} \\ =(1-x^{n})^{m} (1-x) ^{-m} \\ =\sum_{i=0}^{m} C_{m} ^{i} (-x^{n}) ^{i} \cdot \sum_{i=0}^{\infty} C_{m+i-1} ^{m-1} x^{i}

到了这一步,我们就可以直接计算了,我们需要求x^k次项的系数,x^k项的系数为

C_{m}^{0}x^{0} \cdot C_{m+k-1}^{m-1}x^{k} - C_{m}^{1}x^{n} \cdot C_{m+k-n-1}^{m-1}x^{k-n} +...-...\\ \\+(-1)^{k/n} \cdot C_{m}^{k/n}x^{n \cdot (k/n)} \cdot C_{m+k-n\cdot (k/n)-1}^{m-1} x^{k-n\cdot (k/n)}\\ \\ = \sum_{i=0}^{k/n}(-1)^{i} \cdot C_{m}^{i} \cdot C_{m+k-n\cdot i-1}^{m-1} \cdot x^{k}

 

代码如下:

#include 
using namespace std;
#define ll long long
const int mod = 998244353;

ll f[200005];
ll ff[200005];
ll a[100005];
ll b[100005];

long long inv(long long a,long long m)
{
	if(a == 1)return 1;
	return inv(m%a,m)*(m-m/a)%m;
}

int t,n,m,k;

ll inline c(int n,int m)
{
	return f[n]*ff[m]%mod*ff[n-m]%mod;
}
 
int main()
{
    f[0]=1;ff[0]=1;
    for (int i=1;i<=200000;i++)
    {
    	f[i]=f[i-1]*i%mod;
    	ff[i]=inv(f[i],mod);
    }
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d%d%d",&n,&m,&k);
        if (k==0)
        {
        	printf("1\n");
        	continue;
        }
        if ((ll)(n-1)*m

 

你可能感兴趣的:(HDU - 6397 (2018 Multi-University Training Contest 8))