【题目描述】
小 H 是一个热爱运动的孩子,某天他想给自己制定一个跑步计划。小 H 计划跑 n 米,其中第 i(i ≥ 1) 分钟要跑 xi米(xi 是正整数),但没有确定好总时长。由于随着跑步时间增加,小 H 会越来越累,所以小 H 的计划必须满足对于任意 i(i>1) 有 xi ≤ xi-1。现在小 H 想知道一共有多少个不同的满足条件的计划,请你帮助他。两个计划不同当且仅当跑步的总时长不同,或者存在一个 i,使得两个计划中 xi 不相同。由于最后的答案可能很大,你只需要求出答案对 p 取模的结果。
【输入格式】
从文件 running.in 中读入数据。
仅一行两个整数 n,p 表示跑步距离与模数。
【输出格式】
输出到文件 running.out 中。
仅一行一个整数,表示答案模 109 + 7 的值。
【样例1输入】
4 44
【样例1输出】
5
【样例1解释】
五个不同的计划分别是:{1,1,1,1},{2,1,1},{3,1},{2,2},{4}。
【样例2输入】
66 666666
【样例2输出】
323522
【样例3输入】
66666 66666666
【样例3输出】
45183149
【数据范围与提示】
对于所有测试点:1 ≤ n ≤ 105, 1 ≤ p < 230。
每个测试点限制具体如下:
测试点编号 | n ≤ |
---|---|
1 | 5 |
2 | 10 |
3 | 50 |
4 | 100 |
5 | 500 |
6 | 2000 |
7 | 5000 |
8 | 20000 |
9 | 50000 |
10 | 100000 |
分析:
(1)左侧数必须比右边数大处理比较复杂
(2)递归调用函数解决此题
run(n,m)代表某数及之后所有数之和为n,最大数不得超过m
for循环表示在最大数之下(i<=m&&i<=n),此位分别为i之后再进入右边所有数的run()中。
AC的C++代码如下:
#include<iostream>
using namespace std;
int n,p,sum;
int run(int n,int m)//n为数的和,m为不能超过的数
{
int x=0;
if(n==1||n==0||m==1)//边际条件
return 1;
else
{
for(int i=1;i<=m&&i<=n;i++)
x+=run(n-i,i);
return x;
}
}
int main()
{
freopen("running.in","r",stdin);
freopen("running.out","w",stdout);
cin>>n>>p;
sum=run(n,n);
sum%=p;//对p取余
cout<<sum;
fclose(stdin);
fclose(stdout);
return 0;
}