2023-07-09:给定N、M两个参数,

一共有N个格子,每个格子可以涂上一种颜色,颜色在M种里选,

当涂满N个格子,并且M种颜色都使用了,叫一种有效方法。

求一共有多少种有效方法。

1 <= N, M <= 5000。

返回结果比较大,请把结果 % 1000000007 之后返回。

答案2023-07-09:

这两种算法用于计算涂色的有效方法总数。

算法 ways1

1.初始化路径数组 path,颜色是否使用的数组 set

2.调用 process 函数,传入初始参数:路径数组 path,颜色是否使用的数组 set,当前处理的位置 i,格子数量 n,颜色种类 m

3.如果当前位置 i 等于格子数量 n,即路径数组 path 已填满:

  • 将颜色是否使用的数组 set 中所有元素重置为 false

  • 统计路径数组 path 中不重复的颜色数量,并记录在 colors 中。

  • 如果 colors 等于颜色种类 m,说明此路径是有效方法,返回 1;否则返回 0。

4.否则,遍历颜色种类 m 的所有可能颜色:

  • 在路径数组 path 当前位置 i 处填入该颜色。

  • 调用 process 函数递归处理下一个位置 i+1

  • 将返回的结果累加到 ans 上。

5.返回最终的结果 ans

算法 ways2

1.初始化动态规划数组 dp,大小为 MAXN × MAXN

2.对于 dp 数组的第一行,设置每个位置的值为颜色种类 m

3.使用两层循环,从第二行开始,依次计算每个位置 dp[i][j] 的值:

  • dp[i][j] 等于前一行 dp[i-1][j] 乘以颜色种类 j 取模 mod

  • 添加额外的项,dp[i][j] 等于前一行 dp[i-1][j-1] 乘以剩余颜色种类 m-j+1,然后加上之前的结果,再取模 mod

4.返回 dp[n][m] 的结果作为最终的答案。

功能测试:逐个测试从 1 到 9 的格子数量和颜色种类的组合,比较两种算法的结果是否一致,如果不一致则输出错误信息并中断。

性能测试:以 N=5000、M=4877 为例,计算两种算法的运行时间并打印结果。

算法 ways1 的时间复杂度为O(m^n),空间复杂度为O(n)。

算法 ways2 的时间复杂度为O(nm),空间复杂度为O(nm)。

go完整代码如下:

package main

import (
"fmt"
"time"
) const MAXN = 5001
const mod = 1000000007 var dp [MAXN][MAXN]int func ways1(n int, m int) int {
path := make([]int, n)
set := make([]bool, m+1)
return process(path, set, 0, n, m)
} func process(path []int, set []bool, i int, n int, m int) int {
if i == n {
for j := 0; j <= m; j++ {
set[j] = false
}
colors := 0
for _, c := range path {
if !set[c] {
set[c] = true
colors++
}
}
if colors == m {
return 1
} else {
return 0
}
} else {
ans := 0
for j := 1; j <= m; j++ {
path[i] = j
ans += process(path, set, i+1, n, m)
}
return ans
}
} func ways2(n int, m int) int {
for i := 1; i <= n; i++ {
dp[i][1] = m
}
for i := 2; i <= n; i++ {
for j := 2; j <= m; j++ {
dp[i][j] = int((int64(dp[i-1][j]) * int64(j)) % mod)
dp[i][j] = int((int64(dp[i-1][j-1])*(int64(m-j+1)) + int64(dp[i][j])) % mod)
}
}
return dp[n][m]
} func main() {
N := 9
M := 9
fmt.Println("功能测试开始")
for n := 1; n <= N; n++ {
for m := 1; m <= M; m++ {
ans1 := ways1(n, m)
ans2 := ways2(n, m)
if ans1 != ans2 {
fmt.Println("出错了!")
fmt.Println("n : ", n)
fmt.Println("m : ", m)
fmt.Println("ans1 : ", ans1)
fmt.Println("ans2 : ", ans2)
break
}
}
}
fmt.Println("功能测试结束") fmt.Println("性能测试开始")
n := 5000
m := 4877
fmt.Println("n : ", n)
fmt.Println("m : ", m)
start := currentTimeMillis()
ans := ways2(n, m)
end := currentTimeMillis()
fmt.Println("取余之后的结果 : ", ans)
fmt.Println("运行时间 : ", (end - start), " 毫秒")
fmt.Println("性能测试结束")
} func currentTimeMillis() int64 {
return time.Now().UnixNano() / int64(time.Millisecond)
}

rust完整代码如下:

fn ways1(n: i32, m: i32) -> i32 {
let mut path = vec![0; n as usize];
let mut set = vec![false; (m + 1) as usize];
process(&mut path, &mut set, 0, n, m)
} fn process(path: &mut [i32], set: &mut [bool], i: i32, n: i32, m: i32) -> i32 {
if i == n {
set.iter_mut().for_each(|x| *x = false);
let mut colors = 0;
for &c in path.iter() {
if !set[c as usize] {
set[c as usize] = true;
colors += 1;
}
}
return if colors == m { 1 } else { 0 };
} else {
let mut ans = 0;
for j in 1..=m {
path[i as usize] = j;
ans += process(path, set, i + 1, n, m);
}
ans
}
} const MAXN: usize = 5001; const MOD: i64 = 1000000007; static mut DP: [[i32; MAXN]; MAXN] = [[0; MAXN]; MAXN]; fn ways2(n: i32, m: i32) -> i32 {
unsafe {
for i in 1..=n {
DP[i as usize][1] = m;
}
for i in 2..=n {
for j in 2..=m {
DP[i as usize][j as usize] =
((DP[(i - 1) as usize][j as usize] as i64 * j as i64) % MOD) as i32;
DP[i as usize][j as usize] = (((DP[(i - 1) as usize][(j - 1) as usize] as i64
* (m - j + 1) as i64)
+ DP[i as usize][j as usize] as i64)
% MOD) as i32;
}
}
DP[n as usize][m as usize]
}
} fn main() {
let n: i32 = 9;
let m: i32 = 9;
println!("功能测试开始");
for n_val in 1..=n {
for m_val in 1..=m {
let ans1 = ways1(n_val, m_val);
let ans2 = ways2(n_val, m_val);
if ans1 != ans2 {
println!("出错了!");
println!("n : {}", n_val);
println!("m : {}", m_val);
println!("ans1 : {}", ans1);
println!("ans2 : {}", ans2);
break;
}
}
}
println!("功能测试结束"); println!("性能测试开始");
let n_val: i32 = 5000;
let m_val: i32 = 4877;
println!("n : {}", n_val);
println!("m : {}", m_val);
let start = std::time::Instant::now();
let ans = ways2(n_val, m_val);
let duration = start.elapsed();
println!("取余之后的结果 : {}", ans);
println!("运行时间 : {} 毫秒", duration.as_millis());
println!("性能测试结束");
}

c++完整代码如下:

#include <iostream>
#include <vector> using namespace std; const int MAXN = 5001;
const int mod = 1000000007; vector<vector<int>> dp(MAXN, vector<int>(MAXN, 0)); int process(vector<int>& path, vector<bool>& set, int i, int n, int m); int ways1(int n, int m) {
vector<int> path(n, 0);
vector<bool> set(m + 1, false);
return process(path, set, 0, n, m);
} int process(vector<int>& path, vector<bool>& set, int i, int n, int m) {
if (i == n) {
fill(set.begin(), set.end(), false);
int colors = 0;
for (int c : path) {
if (!set[c]) {
set[c] = true;
colors++;
}
}
return colors == m ? 1 : 0;
}
else {
int ans = 0;
for (int j = 1; j <= m; j++) {
path[i] = j;
ans += process(path, set, i + 1, n, m);
}
return ans;
}
} int ways2(int n, int m) {
for (int i = 1; i <= n; i++) {
dp[i][1] = m;
}
for (int i = 2; i <= n; i++) {
for (int j = 2; j <= m; j++) {
dp[i][j] = ((long)dp[i - 1][j] * j) % mod;
dp[i][j] = (((long)dp[i - 1][j - 1] * (m - j + 1)) + dp[i][j]) % mod;
}
}
return dp[n][m];
} int main() {
int N = 9;
int M = 9;
cout << "功能测试开始" << endl;
for (int n = 1; n <= N; n++) {
for (int m = 1; m <= M; m++) {
int ans1 = ways1(n, m);
int ans2 = ways2(n, m);
if (ans1 != ans2) {
cout << "出错了!" << endl;
cout << "n : " << n << endl;
cout << "m : " << m << endl;
cout << "ans1 : " << ans1 << endl;
cout << "ans2 : " << ans2 << endl;
break;
}
}
}
cout << "功能测试结束" << endl; cout << "性能测试开始" << endl;
int n = 5000;
int m = 4877;
cout << "n : " << n << endl;
cout << "m : " << m << endl;
long long start = clock();
int ans = ways2(n, m);
long long end = clock();
cout << "取余之后的结果 : " << ans << endl;
cout << "运行时间 : " << (end - start) << " 毫秒" << endl;
cout << "性能测试结束" << endl; return 0;
}

2023-07-09:给定N、M两个参数, 一共有N个格子,每个格子可以涂上一种颜色,颜色在M种里选, 当涂满N个格子,并且M种颜色都使用了,叫一种有效方法。 求一共有多少种有效方法。 1 <= N,的更多相关文章

  1. 已知n个数的入栈序列,求一共有多少种出栈序列 (卡特兰数)

    已知\(n\)个数的入栈序列,求一共有多少种出栈序列 这个经典问题有两种解法. 解法一: 设\(f(x)\)为\(x\)个数入栈后,再全部出栈的序列数量 假设我们有\(4\)个数\(a,b,c,d\) ...

  2. 有n个台阶,如果一次只能上1个或2个台阶,求一共有多少种上法

    // n级台阶,求多少种跳法.cpp : Defines the entry point for the console application. // /* 思路: 如果只有一级台阶,n=1,很明显 ...

  3. hdu2049 不容易系列之(4)——考新郎 错排+组合 一共有N对新婚夫妇,N个新娘随机坐成一排,每个新郎只能选一个, 其中有M个新郎找错了新娘,求发生这种情况一共有多少种可能.

    不容易系列之(4)——考新郎 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...

  4. 算法基础_递归_给定m个A,n个B,一共有多少种排列

    问题描述: 给定m个A,n个B,一共有多少种排列 解题源代码: /** * 给定m个A,n个B,问一共有多少种排列 * @author Administrator * */ public class ...

  5. n个台阶,每次都可以走一步,走两步,走三步,走到顶部一共有多少种可能

    分析 第一个台阶  1第二个台阶  11 2    //走两次1步或者走1次两步第三个台阶  111 12 21 3 第四个台阶  1111 112 121 211 22 13 31 思想:4阶台阶, ...

  6. Android 一共有多少种动画?准确告诉你!

    Android 动画 Android 动画在开发中是不可或缺的功能,或者说是界面灵动的添加剂.那你是否总结过 Android 中总共为开发者提供了多少种方式的动画呢?今天就为大家总结归纳一下.   报 ...

  7. python假设一段楼梯共 n(n>1)个台阶,小朋友一步最多能上 3 个台阶,那么小朋友上这段楼 梯一共有多少种方法

    我们先把前四节种数算出来(自己想是哪几类,如果你不会算,那就放弃写代码吧,干一些在街上卖肉夹馍的小生意,也挣得不少) 标号 1    2    3     4 种类 1    2    4     7 ...

  8. 爬楼梯,N级楼梯有多少种走法?

    https://blog.csdn.net/tcpipstack/article/details/45173685 一个人爬楼梯,一步可以迈一级,二级,三级台阶,如果楼梯有N级,要求编写程序,求总共有 ...

  9. F - Goldbach`s Conjecture 对一个大于2的偶数n,找有多少种方法使两个素数的和为n;保证素数a<=b; a+b==n; a,b都为素数。

    /** 题目:F - Goldbach`s Conjecture 链接:https://vjudge.net/contest/154246#problem/F 题意:对一个大于2的偶数n,找有多少种方 ...

  10. 2021.07.09 K-D树

    2021.07.09 K-D树 前置知识 1.二叉搜索树 2.总是很长的替罪羊树 K-D树 建树 K-D树具有二叉搜索树的形态,对于每一个分类标准,小于标准的节点在父节点左边,大于标准的节点在父节点右 ...

随机推荐

  1. Golang 常用库之jwt-go

    本文地址 https://www.cnblogs.com/zichliang/p/17303759.html github地址:https://github.com/dgrijalva/jwt-go ...

  2. day49:django:wsgrief&模板渲染Jinjia2&django的MTV/MVC框架&创建/启动一个django项目

    目录 1.自定义web框架wsgiref版 2.自定义web框架wsgiref版-优化版 3.模板渲染JinJa2 4.MTV和MVC框架 5.django:下载安装&创建启动 自定义web框 ...

  3. mysql迁移:mysqldump导出表结构及数据

    问题描述:有需要mysql某几张表的需求,某个数据库某几张表,导出先检查相应的数据库和表是否存在 数据泵用法:默认导出的是表结构以及表中的数据 mysqldump -uroot -p -S /data ...

  4. MySQL MHA信息的收集【Filebeat+logstash+MySQL】

    一.项目背景 随着集团MHA集群的日渐增长,MHA管理平台话越来越迫切.而MHA平台的建设第一步就是将这些成百上千套的MHA集群信息收集起来,便于查询和管理. MHA主要信息如下: (1)基础配置信息 ...

  5. VUE3企业级项目基础框架搭建流程(1)

    开发环境和技术栈 操作系统 windows11 开发工具 vscode.phpstudy(小皮):nginx1.15.11, mysql5.7.26, php7.4,Navicat for MySQL ...

  6. 如何在 .NET Core WebApi 中处理 MultipartFormDataContent 中的文件

    在上一篇文章(如何在 .NET Core WebApi 中处理 MultipartFormDataContent)中,我们有描述过如何以最简单的方式在 .NET Core WebApi 中处理 Mul ...

  7. extend笔记

    JavaScript面向对象 继承extend 1. 概念(主要用途) 将子类中的共性代码 ( 属性和方法 ) 抽取出来 放到父类中 每当有一个新的子类需要用到共性的属性或者方法时 不需要在自己内容复 ...

  8. react中受控组件与非受控组件--

    非受控组件:随用随取 1 render() { 2 return ( 3 <div> 4 <h1>非受控组件</h1> 5 <form action=&quo ...

  9. Python-获取Local Storage和Session Storage

    一.简介 LocalStorage 是只读的.数据存储也是跨浏览器会话.LocalStorage 类似于SessionStorage. 区别在于,数据存储在 LocalStorage 是无期限的,而当 ...

  10. VS2022使用ClickOnce发布程序本地安装.net框架

    因为遇到下面的错误,没有在网上搜到详细解决问题的教程,费了一些时间才解决了问题,特此记录一下,也希望能帮助到其他人. 要在"系统必备"对话框中启用"从与我的应用程序相同的 ...