【题解】[wikioi2520]上学路线

本文介绍了一道关于组合数计算的经典例题及其解决方法。通过分析题目背景,采用高精度计算方式来求解组合数C(m+n,n),并提供了一个C++实现示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目地址:http://www.wikioi.com/problem/2505/

今天找了两道数学题稍微练习了一下。。。

这一道比较水。

这是一道递推的经典例题的数据加强版。。。但因为数据范围太大,明显不用递推。。。

然后,这道题也是一道组合的经典例题:

根据题意,小A一共要走m+n步,其中有n步是横着在走。。。可以想到,每一种走法都是在这m+n步中选择不同的n步作为横着走的情况。。。。实际上就是组合数C(m+n,n).

现在关键问题就是这个m+n怎么算。首先明确的是一定要用高精度。

对于组合数的计算,可以用C(n,r)=C(n-1,r)+C(n-1,r-1)这个公式。。。但是其实这样复杂度是比较高的,并不适用

那怎么办?。。套公式即可。。。只不过不能硬算阶乘,要边乘边除。(相当于用C(n,r+1)=C(n,r)*(n-k)/(k+1)这个公式从C(n,0)开始推)

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=10000000;
struct bign
{
	long long num[2000],len;
	bign()
	{
		memset(num,0,sizeof(num));
		len=1;
	}
	bign operator =(int x)
	{
		len=0;
		while(x)
		{
			num[len++]=x%M;
			x/=M;
		}
		if(len==0)len=1;
		return *this;
	}
	bign operator =(const bign &b)
	{
		len=b.len;
		for(int i=0;i<len;i++)num[i]=b.num[i];
		return *this;
	}
	bign operator *(int x)
	{
		bign c;
		c.len=len;
		for(int i=0;i<len;i++)
		{
			c.num[i]=x*num[i];
		}
		long long temp=0;
		for(int i=0;i<c.len;i++)
		{
			c.num[i]+=temp;
			temp=c.num[i]/M;
			c.num[i]=c.num[i]%M;
			if(i==c.len-1&&temp!=0)
			{
				c.len++;
			}
		}
		return c;
	}
	bign operator /(int x)
	{
		bign c;
		c.len=len;
		long long temp=0;
		for(int i=len-1;i>=0;i--)
		{
			temp*=M;
			temp+=num[i];
			if(temp>x)
			{
				c.num[i]=temp/x;
				temp-=c.num[i]*x;
			}
		}
		while(c.len&&c.num[c.len-1]==0)c.len--;
		if(c.len==0)c.len=1;
		return c;
	}
	void print()
	{
		printf("%d",num[len-1]);
		for(int i=len-2;i>=0;i--)printf("%07lld",num[i]);
		printf("\n");
	}
};
int N,m;
bign C(int n,int k)
{
	bign ret;
	ret=1;
	for(int i=1;i<=k;i++)
	{
		ret=ret*(n-i+1)/i;
	}
	return ret;
}
int main()
{
	scanf("%d%d",&N,&m);
	bign ans;
	ans=C(N-1+m-1,min(N-1,m-1));
	ans.print();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值