算法----数的划分

下面的三题皆是同一类型的题,此处放在一起

1、 NKOJ3527 数的划分(统一只讲一种思想的解法)

时间限制 : 10000 MS 空间限制 : 65536 KB

问题描述

将整数n分成k份,且每份不能为空,任意两份不能相同(不考虑顺序)。

例如:n=7,k=3,下面三种分法被认为是相同的。

1,1,5; 1,5,1; 5,1,1;

问有多少种不同的分法。

 

输入格式

n,k (6< n<=200,2<=k<=6)

 

输出格式

一个整数,即不同的分法。

 

样例输入

7 3

 

样例输出

4

{四种分法为:1,1,5;1,2,4;1,3,3;2,2,3;}

 

思路:

设f[i][j]表示i分为j个数的方案数,

在f[i][j]的所有方案中,含1的为f[i-1][j-1],不含的,考虑将所有数字减去1,所以方案数为f[i-j][j]

f[i][[j]=f[i-1][j-1]+f[i-j][j]

递归的方式求解:

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		int n,k;
		Scanner sc = new Scanner(System.in);
		n=sc.nextInt();
		k=sc.nextInt();
		int count = f(n,k);
		System.out.println(count);
	}

	private static int f(int n, int k) {
		//当被划分的数分完时,此时不能够再划分,返回0;
		//当划分的次数大于划分的数时,此时将n以最小的一来划分也不够,说明此时是不满足条件结果
		if(n==0 || k>n) return 0; 
		if(n==1 || k==n || k==1)return 1;//满足条件的情况
		return f(n-1,k-1)+f(n-k,k);
	}
	
}
动态规划的方式求解:

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		int n,k;
		Scanner sc = new Scanner(System.in);
		n=sc.nextInt();
		k=sc.nextInt();
		
		int[][] f = new int[10001][10001];
		f[1][1]=1;
		for(int i=2;i<=n;i++){
			for(int j=1;j<=k && j<=i;j++){
				f[i][j] = f[i-1][j-1] + f[i-j][j];
			}
		}
		System.out.println(f[n][k]);
	}

}

2、 NKOJ 3526 放苹果

时间限制 : 10000 MS 空间限制 : 65536 KB

 

问题描述

一天,Formiko由于成绩优秀,得到了何老板赏赐的m个完全相同的苹果。他觉得何老板赏赐的东西十分有纪念价值,就准备把这些苹果放到n个完全相同的盘子里保存起来。但这时患有重度强迫症的Formiko想知道将m个苹果放入n个盘子共有多少种放的方案,否则他就不能放入了(悲剧啊!)。但是苹果和盘子也许有很多,显然方案就会有很多,Formiko不能把所有的方案数全部数清楚,所以这个艰巨而又坑壁的任务就交给你了。(答案对1000007取模)

但Formiko还是没有如此作死地把任务全部交给你,他给了你两点十分重要的提示提示:1、允许有的盘子空着不放;2、例如5,1,1和1,1,5是同一种放法。

 

输入格式

一行,两个整数m,n,分别表示m个苹果和n个盘子。

 

输出格式

一行,一个整数ans,表述方案总数。

 

样例输入

7 3

 

样例输出

8

 

提示

1<=m,n<=2000

 

思路:

法一:

同题1,f[i][j]表示将i个苹果放满 j个盘子的方案数;

f[i][j]=f[i-1][j-1]+f[i-j][j]

因为可以空,所以求sum

动态规划的方式求解:
import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		int m,n;
		Scanner sc = new Scanner(System.in);
		m=sc.nextInt();
		n=sc.nextInt();
		int[][] f = new int[10001][10001];
		f[1][1] = 1;
		for(int i=2;i<=m;i++){
			for(int j=1;j<=n && j<=i;j++){
				f[i][j]=(f[i-1][j-1]+f[i-j][j])%1000007;
			}
		}
		int ans=0;
		for(int k=1;k<=m;k++)ans+=f[m][k];
		System.out.println(ans);
	}

}
递归的方式此处省略

3、 NKOJ3131 自然数的拆分

时间限制 : 10000 MS 空间限制 : 65536 KB

 

问题描述

任何一个大于1的自然数N,总可以拆分为若干个自然数之和,并且有多种拆分方法。

例如,自然数5,可以有以下一些拆分方法:

5=1+1+1+1+1

5=1+1+1+2

5=1+1+3

5=1+2+2 ( 5=2+1+2,5=2+2+1,看成同一种拆分)

5=1+4 ( 5=4+1看成同一种拆分)

5=2+3 ( 5=3+2看成同一种拆分)

请设计一个对任意自然数,找出所有拆分方法的程序。

 

输入格式

一个正整数n,(2<=n<=35)

 

输出格式

第一行,一个整数t,表示拆分的总方案数

 

样例输入

样例输入1:

5

样例输入2:

6

 

样例输出

样例输出1:

6

样例输出2:

10

 

提示

样例2说明

10种方案如下:

6=1+1+1+1+1+1

6=1+1+1+1+2

6=1+1+1+3

6=1+1+2+2

6=1+1+4

6=1+2+3

6=1+5

6=2+2+2

6=2+4

6=3+3

 

思路: //状态转移不下去就加维

法一:

同题1/题2法一,f[i][j]表示将i划分为j个数的方案数;

f[i][j]=f[i-1][j-1]+f[i-j][j]

递归的方式求解:

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int ans = 0;
		for(int i=1;i<n;i++){
			ans+=f(n,i);
		}
		System.out.println(ans);
	}

	private static int f(int n, int i) {
		if(n==0 || i > n) return 0;
		if(n==1 || i==1 || n==i) return 1;
		return f(n-1,i-1) + f(n-i,i);
	}

}
动态规划的方式求解:

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int ans = 0;
		int[][] f = new int[10001][10001];
		f[1][1]=1;
		for(int i=2;i<=n;i++){
			for(int j=1;j<=i;j++){
				f[i][j] = f[i-1][j-1] + f[i-j][j];
			}
		}
		for(int k=1;k<n;k++)ans+=f[n][k];
		System.out.println(ans);
	}

}


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LRU(Least Recently Used)是一种常见的缓存淘汰算法,它的基本思想是:将最不常用的据最先淘汰掉。 具体实现方式通常是将缓存空间划分为若干个桶(bucket),每个桶中存储一组据,同时记录它们最后一次被访问的时间。当缓存空间满了,需要淘汰一些据时,LRU算法会根据据最近使用的频率和时间进行淘汰。 算法的核心思想是通过计器(例如最近访问计器)和哈希表(或排序列表)来实现。计器用于记录每个据项最后一次被访问的时间,哈希表或排序列表用于快速查找和删除据项。 具体实现步骤如下: 1. 当缓存空间满了,需要淘汰一些据时,遍历缓存中的所有据项,并记录它们最后一次被访问的时间。 2. 根据时间戳和计器的值,将据项按照最近使用的频率进行排序。 3. 将排名最靠后的据项从缓存中删除,并释放相应的空间。 4. 如果需要继续淘汰据,重复步骤1-3,直到缓存空间不再满为止。 这种算法的优点是实现简单,易于理解和实现,并且具有较好的性能和效率。但是,它也有一些缺点,例如当缓存命中率较低时,需要频繁地进行淘汰和替换操作,导致缓存命中率进一步下降。此外,如果需要支持高并发访问,还需要考虑并发控制和线程安全等问题。 总之,LRU算法是一种常用的缓存淘汰算法,适用于需要快速响应和低延迟的应用场景。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值