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
生成公式:
这个公式就是就可以表示第m行的结果,对应的系数就是展开式中x^i的系数,所以我们只需要求生成公式中x^k的系数即可。
那么我们就得对公式化简
根据泰勒展开:
可得
所以
到了这一步,我们就可以直接计算了,我们需要求x^k次项的系数,x^k项的系数为
代码如下:
#include <bits/stdc++.h>
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<k)
{
printf("0\n");
continue;
}
ll ans=0;
for (int i=0;i<=k/n;i++)
{
ll x=c(m,i)*c(m+k-i*n-1,m-1)%mod;
if (i%2==0) ans=(ans+x)%mod;
else ans=(ans-x+mod)%mod;
}
printf("%lld\n",ans);
}
return 0;
}