hdu6363组合数学+容斥+扩展欧拉

参考:DLS的代码orz,官方题解

 

前置技能:

1.N个相同的球放K个不同盒子,可以空盒:C(n+k-1,k-1)(插板法可证)

2.第二行到第三行可以归纳证明

3.扩展欧拉公式,phi(p)=p-1

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int _=1000005;
int fb[_];//斐波那契 
int jc[2*_];//阶乘 
int jv[2*_];//阶乘的逆元 
int qmod(int a,int b)
{
	int res=1;while(b)
	{
		if(b&1)res=1ll*res*a%mod;
		a=1ll*a*a%mod;b=b>>1;
	}
	return res;
}
void init()
{
	fb[0]=0;fb[1]=1;jc[0]=1;jv[0]=1;
	for(int i=2;i<_-2;i++)fb[i]=1ll*(fb[i-1]+fb[i-2])%(mod-1);//扩展欧拉 %(mod-1) 
	for(int i=1;i<2*_;i++)jc[i]=1ll*jc[i-1]*i%mod;
	jv[2*_-1]=qmod(jc[2*_-1],mod-2);
	for(int i=2*_-2;i>=1;i--)jv[i]=1ll*jv[i+1]*(i+1)%mod;	
} 
vector<int>d;int ans[_];
void get(int n)//得N的因子 
{
	for(int i=1;i<=n/i;i++)
		if(n%i==0)
		{
			if(n!=i*i)d.push_back(i),d.push_back(n/i);
			else d.push_back(i);	
		}	
	sort(d.begin(),d.end());
}
int getC(int a,int b)
{
	return 1ll*jc[a]*jv[b]%mod*jv[a-b]%mod;
}
int main()
{
	init();
	//printf("%d\n",getC(7,3));
	int T;scanf("%d",&T);
	while(T--)
	{
		int n,k;scanf("%d %d",&n,&k);int res=0;
		d.clear();get(n);
		for(int i=0;i<d.size();i++)ans[i]=getC(n/d[i]+k-1,k-1)%mod;//枚举gcd为d[i],剩下n/d[i]球个分到k个不同的盒子里,可以空盒 
		
		//至此,ans[i]:gcd至少为i的方案数
		//举个例子N=8,ans[2]=f[2]+f[4]+f[8];ans[4]=f[4]+f[8];ans[8]=f[8]; 
			
		for(int i=d.size()-1;i>=0;i--)
			for(int j=i+1;j<d.size();j++)
				if(d[j]%d[i]==0)ans[i]=1ll*(ans[i]-ans[j]+mod)%mod;//因子容斥 ,算是常见套路! 
				
		//for(int i=0;i<d.size();i++)printf("%d %d %d\n",d[i],ans[i],fb[d[i]]);		
		
		//至此,ans[i]:gcd为i的方案数		
		for(int i=0;i<d.size();i++)
			(res+=1ll*ans[i]*(qmod(2,fb[d[i]])-1)%mod )%=mod;//对每个gcd算贡献 
			
		res=1ll*res*qmod(getC(n+k-1,k-1),mod-2)%mod;//除以总情况,便是期望 
		printf("%d\n",(res+mod)%mod);
	}	
} 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值