莫的难题
题目大意
有五个数字,分别是 5、2、1、3、9
。
可以取任意数字,每个数字可以取无限次。
如:取两个 5
,则组合为:55
;取 2
与 1
,则组合为: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
对应 9
,1
对应 1
,2
对应 2
,3
对应 3
,4
对应 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
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 常用的键盘事件
- SpringMVC对接CAS客户端实现单点登录手册
- 什么是BOM
- Servlet3.0动态配置过滤器、监听器、Servlet
- JS执行机制
- 元素偏移量 offset 系列
- 设计模式系列之建造者模式构建实体类
- 元素可视区 client 系列
- 【阿里】在 nginx 中如何配置负载均衡
- 并发编程系列之JDK JUC实现内存缓存(支持并发)
- 10.1【前端开发】背景属性:样式中背景色和背景图片样式如何使用?
- 元素滚动 scroll 系列
- Java基础系列之fastjson parse多级json数据
- Linux系列之下载安装jdk-8u261-linux-i586.tar.gz
- 常见网页特效案例