Codeforces 225B. Well-known Numbers (数学)

Description
Numbers k-bonacci ( k is integer, k > 1) are a generalization of Fibonacci numbers and are determined as follows:

F(k, n) = 0, for integer n, 1 ≤ n < k;
F(k, k) = 1;
F(k, n) = F(k, n - 1) + F(k, n - 2) + … + F(k, n - k), for integer n, n > k.

Note that we determine the k-bonacci numbers, F(k, n), only for integer values of n and k.

You’ve got a number s, represent it as a sum of several (at least two) distinct k-bonacci numbers.

Input
The first line contains two integers s and k ( 1   ≤   s ,   k   ≤   1 0 9 ; k   >   1 ) k (1 ≤ s, k ≤ 10^9; k > 1) k(1s,k109;k>1).

Output
In the first line print an integer m (m ≥ 2) that shows how many numbers are in the found representation. In the second line print m distinct integers a 1, a 2, …, a m. Each printed integer should be a k-bonacci number. The sum of printed integers must equal s.

It is guaranteed that the answer exists. If there are several possible answers, print any of them.

Examples
Input
5 2
Output
3
0 2 3

Input
21 5
Output
3
4 1 16

Solution
首先推出k-波那契通项公式

//这里的f[0] 相当于题目中的 f[k][k]
f[0] = f[1] = 1;
for(int i = 2;;++i){
	if(i <= k) f[i] = f[i-1] * 2;
	else f[i] = 2 * f[i-1] - f[i-k-1];
}

我们发现前k项为2的次幂,增长很快。而且打表发现,当k最小为2时,整个数列也很快就增长到 s 的最高数量级(1e9)
所以我们可以暴力求出数列直到增长到s的部分,显然需要从大到小依次判断,能取就取
题目还要求至少取2个数,所以我们可以再拿一个前面k-1项中的0充数

Code

int tot = 0;
ll f[maxn];

void init(int k,int s){
	f[0] = f[1] = 1;
	for(int i = 2;;++i){
		if(i <= k){
			f[i] = f[i-1] * 2;
		} else f[i] = 2 * f[i-1] - f[i-k-1];
		if(f[i] >= s) {tot = i;break;}
	}
}
vector<int>ans;
map<ll,bool>mp;
int main() {
	int s,k;scanf("%d%d",&s,&k);
	init(k,s);
	for(int i = tot;i >= 1;--i){
		if(s >= f[i] && !mp[f[i]]) {
			mp[f[i]] = true;
			ans.pb(f[i]);
			s -= f[i];
		}
	}
	ans.pb(0);
	cout << ans.size() << endl;
	for(auto x : ans) cout << x << " ";
	cout << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值