2018 杭电暑期多校第八场 Character Encoding

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6397

这周多校完全身败名裂。。。。

题意: 求 x1+x2……+xm=k   0<=xi<n 的方案数

           看下这边orzhttps://blog.csdn.net/m0_37286282/article/details/78869512

           就是经典的有限制的方程整数解的问题。。。

 

            在没有限制的情况下,用插板法答案就是 C(k+m-1,m-1)

            现在考虑至少有p个数突破了限制的情况,就是先取p个n 出来,剩下的数没有限制的分成m份,然后再把p个n分到这m份中的p个数里头去就能保证至少有p个数突破了限制 

           令F(x)表示至少有x个数突破限制的方案数

       F(x)=C(m,p)*C(k+m-1-p*n,m-1)

那么我们现在要求突破限制的方案总数,根据容斥原理就是F(1)-F(2)+F(3)..........

总的方案数看成C(m,0)*C(k+m-1,m-1)我们的答案化简下就是

 \sum_{i=0}^{k/n}(-1)^i*C(m,i)*C(k+m-1-i*n,m-1)

 

另外的一种做法是母函数orz

我们第一位相当于(x^0+x^1+x^2......+x^n-1)

一共有m位那么就是(x^0+x^1+x^2......+x^n-1)^m 我们的答案就是其中x^k的系数

 

代码是容斥orz

#include<bits/stdc++.h>
#define ll long long 
#define mod 998244353
#define maxn 203000
using namespace std;

ll f[maxn],fv[maxn];

ll q_pow(ll a,ll b){
	ll ans=1;
	while(b){
		if (b&1)ans=ans*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return ans;
}

void init(){
	f[0]=1;
	for (ll i=1;i<maxn;i++)
	    f[i]=(f[i-1]*i)%mod;
	fv[maxn-1]=q_pow(f[maxn-1],mod-2);
	for(ll i=maxn-1;i>0;i--)
	   fv[i-1]=fv[i]*i%mod; 
}

ll C(ll n,ll m){
	if (n<0||m<0||n<m)return 0;
    return f[n]*(fv[m])%mod*fv[n-m]%mod;
}

int main(){
  ll n,m,k,ans;
  init();
  int t;
  scanf("%d",&t);
  while(t--){
  	   scanf("%lld%lld%lld",&n,&m,&k);
  	   ll ans=0;
  	   for (int c=0;c*n<=k;c++)
  	     if (c&1)ans=(ans-C(m,c)*C(k-c*n-1+m,m-1)%mod+mod)%mod;
  	       else ans=(ans+C(m,c)*C(k-c*n-1+m,m-1)%mod)%mod;
      printf("%lld\n",ans);
  }
}

 

我是真的料理上手orz

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值