1. 程式人生 > >Frog and Portal HihoCoder - 1873(思維)

Frog and Portal HihoCoder - 1873(思維)

A small frog wants to get to the other side of a river. The frog is initially located at one bank of the river (position 0) and wants to get to the other bank (position 200). Luckily, there are 199 leaves (from position 1 to position 199) on the river, and the frog can jump between the leaves. When at position p, the frog can jump to position p+1 or position p+2.

How many different ways can the small frog get to the bank at position 200? This is a classical problem. The solution is the 201st number of Fibonacci sequence. The Fibonacci sequence is constructed as follows: F1=F2=1;Fn=Fn-1+Fn-2.

Now you can build some portals on the leaves. For each leaf, you can choose whether to build a portal on it. And you should set a destination for each portal. When the frog gets to a leaf with a portal, it will be teleported to the corresponding destination immediately. If there is a portal at the destination, the frog will be teleported again immediately. If some portal destinations form a cycle, the frog will be permanently trapped inside. Note that You cannot build two portals on the same leaf.

Can you build the portals such that the number of different ways that the small frog gets to position 200 from position 0 is M?

Input

There are no more than 100 test cases.

Each test case consists of an integer M, indicating the number of ways that the small frog gets to position 200 from position 0. (0 ≤ M < 232)

Output

For each test case:

The first line contains a number K, indicating the number of portals.

Then K lines follow. Each line has two numbers ai and bi, indicating that you place a portal at position ai and it teleports the frog to position bi.

You should guarantee that 1 ≤ K, ai, bi ≤ 199, and ai ≠ aj if i ≠ j. If there are multiple solutions, any one of them is acceptable.

Sample Input

0
1
5

Sample Output

2
1 1
2 1
2
1 199
2 2
2
4 199
5 5

 題目大意:

讓你從0號位置跳到200號位置,每次只能跳一格或是兩格,給你一個數m讓你通過在兩點之間建立傳送門使得能走到終點的所有情況數為m,還給了一些關於斐波那契的東西,還請讀者仔細閱讀一下題目。

解題思路:

首先,要能明白所有的正整數都可以分解成多個斐波那契數的和,那麼我們想辦法這m種情況分成由許多斐波那契數相加的情況。具體如何分呢?我們可以從後往前推,在位置1架設一個傳送門直接傳送到位置pos,然後在位置2架設一個傳送門傳送到位置2,那麼所有的情況就都是從位置pos到終點的情況種數了(一旦到達位置2就gg了,相信聰明的讀者一定明白為什麼)類似於這樣,我們可以在1,3,5,7這些位置架設傳送門(中間要是不隔一個的話是走不過來的,每次可是隻能走一步或者兩步),這個操作也就對應於把m分解成若干個斐波那契數的和,最後的話只需要在最後一個傳送門的下一個位置設定一個自己到自己的傳送門就ok了。仔細理解一下,可能有點繞,畫出示意圖就好理解一點了。

上程式碼。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;

typedef long long ll;

ll fibo[210];

int lt[300], rt[300];

int main()
{
	//freopen("in.txt", "r", stdin);
	ll m;
	fibo[1] = 1;
	fibo[2] = 2;
	for(int i = 3; i <= 210; ++ i)
	{
		fibo[i] = fibo[i - 1] + fibo[i - 2];
	}	
	
	while(cin >> m)
	{
		int cnt = 50;
		int res = 1;
		int top = 0;
		if(m == 0)   //注意還要特判一下,因為答案個數必須要大於一
		{
			cout << 2 << endl << 1 << ' ' << 1 << endl << 2 << ' ' << 1 << endl;
			continue;
		}
		while(m)
		{
			while(fibo[cnt] > m)
			{
				cnt --;
			}
		    lt[top] = res;
			rt[top++] = 200 - cnt;
			res += 2;
			m -= fibo[cnt];
		}
		lt[top] = res - 1;
		rt[top++] = res - 1;
		cout << top << endl;
		for(int i = 0; i < top; ++ i)
		{
			cout << lt[i] << ' ' << rt[i] << endl;
		}
	}

	return 0;
}