莫的难题

时间:2021-08-24
本文章向大家介绍莫的难题,主要包括莫的难题使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题目大意

有五个数字,分别是 5、2、1、3、9

可以取任意数字,每个数字可以取无限次。

如:取两个 5,则组合为:55;取 21,则组合为:21

现在要问你所有组合中第 \(C_{n}^{m} \bmod (10^9+7)\) 个数有多大?

解题思路

题目是先读入 \(n\) 再读入 \(m\)

首先必须得知道:

\(C_{n}^{m}=\frac{\prod\limits_{i=n-m+1}^{n}i}{\prod\limits_{i=1}^{m}i}\)

由于涉及到关于模的的除法,比较好想的是用逆元。

当然,用线性递推(类似于杨辉三角一样的规律)也是可以的。

不过我更想练练手感。

关于逆元,可以参考我的博客,点这里

由于本题的模数是 \(10^9+7\),为质数,故可采用费马小定理求逆元。

\(x\) 的逆元等于 \(x^{p-2} \pmod{p}\)

int M(int n, int m)
{
	long long ans = 1;
	for(int i = n - m + 1; i <= n; ++i) ans = ans * i % p;
	for(int i = 1; i <= m; ++i) ans = ans * qpow(i, p - 2) % p;
	return ans;
}

然后可以想到,可以将十进制转换成五进制,因为输出的答案只可能包括 1、2、3、5、9\(5\) 个数。

故可将 0 对应 91 对应 12 对应 23 对应 34 对应 5

但此时有一个坑点:

假如将我们将十进制数 \(5\) 转换成五进制数,正常来说是 \(10\)

但此时我们真正的答案为 \(0\),输出 \(9\)

再来一个例子,假如将我们将十进制数 \(10\) 转换成五进制数,正常来说是 \(20\)

但此时我们真正的答案为 \(10\),输出 \(19\)

得出,这两个例子的正常得数与真正得数相差五进制数 \(10\),即为十进制数 \(5\)

所以,当我们要进位的时候,应将那一位减一,使得 \(5\) 不会进位。

比较模糊,可以仔细思考一下。

最后注意反过来输出。

string s = "";
while(b > 0)
{
	long long l = b % 5;
	if(b % 5 == 0) b--;
	b /= 5;
//	cout << b % 5 << " ";
	if(l == 1)
	{
		s = "1" + s;
//		printf("1");
	}
	if(l == 2)
	{
		s = "2" + s;
//		printf("2");
	}
	if(l == 3)
	{
		s = "3" + s;
//		printf("3");
	}
	if(l == 4)
	{
		s = "5" + s;
//		printf("5");
	}
	if(l == 0)
	{
		s = "9" + s;
//		printf("9");
	}
}

AC CODE

#include <bits/stdc++.h>
using namespace std;

long long q, n, m;

long long ans;

const long long p = (long long) 1e9 + 7;

long long qpow(long long x, long long y)
{
	long long ans = 1;
	while(y)
	{
		if(y & 1)
		{
			ans = ans * x % p;
		}
		x = x * x % p;
		y /= 2;
	}
	return ans;
}

int M(int n, int m)
{
	long long ans = 1;
	for(int i = n - m + 1; i <= n; ++i) ans = ans * i % p;
	for(int i = 1; i <= m; ++i) ans = ans * qpow(i, p - 2) % p;
	return ans;
}

signed main()
{
	scanf("%lld", &q);
	while(q--)
	{
		scanf("%lld%lld", &n, &m);
		long long opt = M(n, m) % p;
		if(opt == 0)
		{
			printf("0\n");
			continue;
		}
		long long b = opt;
		string s = "";
		while(b > 0)
		{
			long long l = b % 5;
			if(b % 5 == 0) b--;
			b /= 5;
//			cout << b % 5 << " ";
			if(l == 1)
			{
				s = "1" + s;
//				printf("1");
			}
			if(l == 2)
			{
				s = "2" + s;
//				printf("2");
			}
			if(l == 3)
			{
				s = "3" + s;
//				printf("3");
			}
			if(l == 4)
			{
				s = "5" + s;
//				printf("5");
			}
			if(l == 0)
			{
				s = "9" + s;
//				printf("9");
			}
		}
//		cout << endl;
		cout << s << endl;
	}
}

本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/15180983.html

原文地址:https://www.cnblogs.com/orzz/p/15180983.html