2018 杭电多校第六场 sacul

链接:http://acm.hdu.edu.cn/showproblem.php?pid=6372

题意:

           题目倒过来就是题解什么的真是太过分了一定要写博客嘤嘤嘤

           首先是卢卡斯定理

          C(n,m) mod p =  C(n%p,m%p)*C(n/p,m/p)mod p

          一般是用来解决大数求组合数的【C(n/p,m/p)可以继续用卢卡斯定理进行简化】

          但同时不停的整除q和对q求余有没有让你想起 十进制数转q进制数。。。。。

          所以也可以看成C(N,M)等于把n,m看成p进制数后,对应位上数字的组合数的乘积

 

        所以C(i,j)>0 那么就意味着 在p进制下,i的每一位都>=j的对应位上的数字(不然c(i,j)=0最后总的组合数乘积为0)

 

        然后这个矩阵A可以看成图的邻接矩阵,A[i][j]就为从i走一步到j的方案数,A的k次方就为从 i走k步到j的方案数

       同时如果满足在p进制下,i的每一位数字都比j的对应位上的数字大于等于的话 那么对应的图里有一条从i->j的边

 

        然后我们要求的  F[n][k]  是A^k的所有元素和,答案就是在图中走k步的方案数

 

       矩阵的下标是从0到 p^n-1对应的是n位p进制数,在图中走k步意味着要找一个长度为k+1的序列,要求每个数字(n位q进制数)的每一位都大于等于上一个数字的对应位。这n位互相之间不影响,所以对于每一位是找一个长度为k+1的每个元素大于等于0小于p的不下降序列,插板法可得有C(k+p,p-1)种方法,有n位那么就是 F[n][k]=C(k+p,p-1)^n种方法

   最后答案的表达式就是ans = \sum _{j=1}^{k}\sum _{i=1}^{n}\left ( C_{j+p}^{p-1} \right )^{i}

 

代码:

#include<bits/stdc++.h>
#define ll long long

using namespace std;
const int MX=13e5+7;
const int mod=1e9+7;

int prime[MX],tt;
bool no_prime[MX];
ll inv[MX],fac[MX];

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

void init(){
   int n=MX-7;
   for (int i=2;i<=n;i++){
   	    if (!no_prime[i])prime[++tt]=i;
   	    for (int j=1;j<=tt&&i*prime[j]<=n;j++){
   	    	   no_prime[i*prime[j]]=1;
   	    	   if(!i%prime[j])break;
		   }
   }
   
   int p=prime[100000];
   fac[0]=fac[1]=inv[0]=inv[1]=1;
   for (int i=2;i<=p;i++)fac[i]=fac[i-1]*i%mod;
   
   
   inv[p]=q_pow(fac[p],mod-2,mod);
   for (int i=p;i>2;i--)inv[i-1]=inv[i]*i%mod;
   
} 

void solve(){
	int c,n,k;
	scanf("%d%d%d",&c,&n,&k);
	ll p=prime[c];
	ll f=fac[p],ans=0;
	
	for (int j=1;j<=k;j++){
		  f=f*(p+j)%mod;
		  ll a=f*inv[p-1]%mod*inv[j+1]%mod;
		  
		  if (a>1)ans=((ans+(q_pow(a,n+1,mod)-a+mod)*q_pow(a-1,mod-2,mod)))%mod;
		     else ans=(ans+n)%mod;
		     
	}
	printf("%lld\n",ans);
}


int main(){
	init();
	int t;
	scanf("%d",&t);
	while(t--)solve();
	return 0;
} 

 

总结下就是 加深了卢卡斯定理的运用

                   还有邻接矩阵的k次方的含义这点

 

菜鸡落泪orz

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值