问题求解
- 把 M M M 个同样的球放到 N N N 个同样的袋子里,允许有的袋子空着不放,问共有多少种不同的放置方法?(用 K K K 表示)。例如, M = 7 M=7 M=7, N = 3 N=3 N=3 时, K = 8 K=8 K=8;在这里认为 ( 5 , 1 , 1 ) (5,1,1) (5,1,1) 和 ( 1 , 5 , 1 ) (1,5,1) (1,5,1) 是同一种放置方法。
问: M = 8 M=8 M=8, N = 5 N=5 N=5 时, K = K= K=____。
【解析】 n n n个相同的球放入 m m m个相同的盒子( n ≥ m n≥m n≥m),可以有空盒时的放法种数等于将 n n n分解为 m m m个、 ( m - 1 ) (m-1) (m-1)个、 ( m - 2 ) (m-2) (m-2)个、…、 2 2 2个、 1 1 1个数的和的所有种数之和。
将8
分解为 1 1 1个数:8
,共 1 1 1种 将8
分解为 2 2 2个数:1+7
,2+6
,3+5
,4+5
,共 4 4 4种
将8
分解为 3 3 3个数:1+1+6
,1+2+5
,1+3+4
,2+2+4
,2+3+3
,共 5 5 5种
将8
分解为 4 4 4个数:1+1+1+5
,1+1+2+4
,1+1+3+3
,1+2+2+3
,2+2+2+2
,共 5 5 5种
将8
分解为 5 5 5个数:1+1+1+1+4
,1+1+1+2+3
,1+1+2+2+2
,共 3 3 3种
答案:18
- 如图所示,图中每条边上的数字表示该边的长度,则从 A A A 到 E E E 的最短距离是____。
【解析】正权图的最短路,可以使用Dijkstra算法求解。
阅读程序写结果
#include <iostream>
using namespace std;
int fun(int n)
{
if(n == 1)
return 1;
if(n == 2)
return 2;
return fun(n - 2) - fun(n - 1);
}
int main()
{
int n;
cin >> n;
cout << fun(n) << endl;
return 0;
}
输入:7
【解析】模拟递归调用的结果如下:
f(1) | f(2) | f(3) | f(4) | f(5) | f(6) | f(7) |
---|---|---|---|---|---|---|
1 | 2 | -1 | 3 | -4 | 7 | -11 |
输出:-11
2.
#include <iostream>
using namespace std;
const int SIZE = 100;
int main()
{
int p[SIZE];
int n, tot, i, cn;
tot = 0;
cin >> n;
for(i = 1; i <= n; i++)
p[i] = 1;
for(i = 2; i <= n; i++)
{
if(p[i] == 1)
tot++;
cn = i * 2;
while(cn <= n)
{
p[cn] = 0;
cn += i;
}
}
cout << tot << endl;
return 0;
}
输入:30
输出:10
【解析】埃氏筛素数法。 对正实数 x x x,定义 π ( x ) π(x) π(x)为不大于 x x x的素数个数, π ( x ) ≈ x / l n x π(x)≈x/ln x π(x)≈x/lnx,
其中 l n x = l o g e x lnx=log_e^x lnx=logex,为 x x x的自然对数, e = 2.718281828... e=2.718281828... e=2.718281828..., l n 30 ≈ 3 ln30≈3 ln30≈3。
完善程序
- (最大子矩阵和)给出 m m m 行 n n n 列的整数矩阵,求最大的子矩阵和(子矩阵不能为空)。
输入第一行包含两个整数 m m m 和 n n n,即矩阵的行数和列数。之后 m m m 行,每行 n n n 个整数,描述整个矩阵。程序最终输出最大的子矩阵和。
#include <iostream>
using namespace std;
const int SIZE = 100;
int matrix[SIZE + 1][SIZE + 1];
int rowsum[SIZE + 1][SIZE + 1]; //rowsum[i][j]记录第 i 行前 j 个数的和
int m, n, i, j, first, last, area, ans;
int main()
{
cin >> m >> n;
for(i = 1; i <= m; i++)
for(j = 1; j <= n; j++)
cin >> matrix[i][j];
ans = matrix ①;
for(i = 1; i <= m; i++)
②
for(i = 1; i <= m; i++)
for(j = 1; j <= n; j++)
rowsum[i][j] = ③;
for(first = 1; first <= n; first++)
for(last = first; last <= n; last++)
{
④;
for(i = 1; i <= m; i++)
{
area += ⑤;
if(area > ans)
ans = area;
if(area < 0)
area = 0;
}
}
cout << ans << endl;
return 0;
}
【解析】利用前缀和的思想,计算出矩阵第
i
行前j
列的和rowsum[i][j]
。枚举所有列的组合,求出子矩阵和的最大值。
- 空①,初始化
ans
,让其等于矩阵第一行第一列的值matrix[1][1]
,所以应填入[1][1]
- 空②,初始化每行前缀和数组的第
0
项,将其置为 0 0 0,用于之后计算前缀和,所以应填入rowsum[i][0]=0
- 空③,计算第
i
行的前缀和,所以应填入rowsum[i][j-1]+matrix[i][j]
- 空④,初始化
area
为 0 0 0,所以应填入area=0
- 空⑤,使用前缀和数组计算
first
列到last
列的和,rowsum[i][last]-rowsum[i][first-1]
。