算法提高 组合公式求值

http://lx.lanqiao.cn/problem.page?gpid=T397

资源限制

时间限制:1.0s   内存限制:256.0MB

问题描述

  给定n, m,求:

RequireFile.do?fid=8NbAnATquploading.4e448015.gif转存失败重新上传取消

输入格式

  输入一行,包含两个整数n, m。

输出格式

  输出一行,包含求得的值,由于答案可能非常大,请输出此公式除以987654321的余数。

样例输入

3 1

样例输出

162

数据规模和约定

  1<=m<=n<=10^7。

思路:https://blog.dotcpp.com/a/56426

#include<iostream>
#include<ctime>
#define ll long long

using namespace std;

const int N = 10000000 + 5;
const int mod = 987654321;

ll prime[N];
ll stu[N];
ll cnt;

void get_prime(ll n)
{
	for(int i=2; i<=n; i++)
	{
		if(!stu[i]) prime[cnt++] = i;
		for(int j=0; prime[j] * i <= n; j++)
		{
			stu[prime[j]*i] = 1;
			if(i % prime[j] == 0) break;
		}
 	}
}

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

ll f(ll a, ll b)//求a的阶乘里有多少个b如f(5,2)值为3(2,4) 
{
	ll ans = 0;
	while(a)
	{
		ans += a /= b;
	}
	return ans;
}

ll c(ll n, ll m)
{
	ll ans = 1;
	for(int i=0; i<cnt && prime[i]<=n; i++)
	{
		ans = ans * ksm(prime[i], f(n,prime[i]) - f(m,prime[i]) - f(n-m,prime[i])) % mod;
	}
	return ans;
}

ll cal(int n)
{
	ll ans = 1;
	for(int i=1; i<=n; i++)
	{
		ans *= i;
	}
	return ans;
}

int main()
{
	
	ll n,m;
	cin>>n>>m;
	get_prime(n);
	ll cnm = c(n,m);
	ll sum = 0;
	if(n >= 3)
	{
		sum = ksm(2,n-3) * (4 * n % mod + n * (n - 1) % mod * (n + 4) % mod) % mod;
	}
	for(int i=1; i <= n && n < 3; i++)
	{
		sum += cal(n)/cal(i)/cal(n-i) * i * i * i % mod;
	}
	cout<< cnm * sum % mod<<endl;
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值