单点时限: 2.0 sec
内存限制: 256 MB
非负数列项的第1项为0,第2项为1,后面的每项为其前面的 k(2≤k≤10) 项之和(若不存在前面的某个项,计算时以0表示)。
例如: k=3, 则数列项依次为:0,1,1(因前面的项不足3项,计算时以(0)表示,1+0+(0)=1),2,4,……
输入格式
一行由一个空格分隔的正整数 k 和 n。
80%的数据点: 2≤k≤3,1≤n≤10
10%的数据点: 2≤k≤5,1≤n≤50
10%的数据点: 2≤k≤10,1≤n≤100
输出格式
在一行中输出数列的第n项。
样例
input |
---|
2 1 |
output |
0 |
input |
---|
4 6 |
output |
8 |
input |
---|
3 4 |
output |
2 |
思路
一道大数运算题
因为每个数都是前k个数的和并且后面的数一定大于前面的数,所以只需要申请一个k行的二维数组来存放数据。
如果n小于2则直接输出。
通过对下标取模定位到数字所在行,将该行更新为k个数字之和。也就是说对于第i个数的第j位而言,它的数码是所有行的第j位的和再模10。直到把这一行处理完,即新的数字替换了旧的数字。简单说就是模拟一个k个数的竖式加法计算。处理了n-2次(0行和1行初始化为0和1)后退出循环,将目标行从后往前输出即可(去掉前置0)。
ac代码
#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char** argv)
{
int k,n;
cin >> k >> n;
int res[k][100];
for(int i=0;i<k;i++)
{
for(int j=0;j<100;j++)
res[i][j]=0;
}
res[1][0]=1;
if(n==1) cout << 0;
else if(n==2) cout << 1;
else
{
for(int i=2;i<n;i++)
{
int sum=0,carry=0;
for(int j=0;j<100;j++)
{
sum=0;
for(int m=0;m<k;m++)
sum+=res[m][j];
sum+=carry;
res[i%k][j]=sum%10;
carry=sum/10;
}
}
int flag;
for(flag=99;res[(n-1)%k][flag]==0;flag--) ;
for(;flag>=0;flag--)
cout << res[(n-1)%k][flag];
}
return 0;
}