ACM-ICPC北京赛区2018 D Frog and Portal(构造)

版权声明:欢迎转载,请注明此博客地址。 https://blog.csdn.net/Ever_glow/article/details/84036527

时间限制:1000ms

单点时限:1000ms

内存限制:512MB

描述

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?

输入

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)

输出

For each test case:

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

扫描二维码关注公众号,回复: 5928928 查看本文章

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.

样例输入

0
1
5

样例输出

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

有一只青蛙,从0的位置跳到200,每次跳跃的距离是1或2。现在你可以在某些叶子上设置传送点,将其直接传送到某个点,最后使得青蛙到200的方案数位M,输出你设计的方案。

前面很容易控制成为只有一种方案的方法,例如在奇数点设置传送位置,那么这样前面的点只有一种走法,然后就是控制后米娜的方案数和是M就ok啦,需要注意的是任意一个数,总能由几个不同位置的斐波那契数组成,需要从大到小遍历减去就可以。这样前面的奇数点传送200-fib,最后一个奇数点后面的偶数直接自环,这样前面只有一条路,后面相加等于M输出最后的答案和跟方案。

代码实现:

/*
Look at the star
Look at the shine for U
*/
#include<bits/stdc++.h>
#define ll long long
#define PII pair<int,int>
#define sl(x) scanf("%lld",&x)
using namespace std;
const int N = 1e6+5;
const ll mod = 1e18;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1);
ll inv(ll b){if(b==1)return 1; return (mod-mod/b)*inv(mod%b)%mod;}
ll fpow(ll n,ll k){ll r=1;for(;k;k>>=1){if(k&1)r=r*n%mod;n=n*n%mod;}return r;}
ll fib[N];
int main()
{
    ll n,i,j,t,cnt;
    fib[0] = 1;
    fib[1] = 1;
    ll maxx = fpow(2,32);
    for(cnt = 2;;cnt++)
    {
        fib[cnt] = fib[cnt-1]+fib[cnt-2];
        if(fib[cnt] > maxx) break;
    }
    while(~sl(n))
    {
        if(n == 0)
        {
            printf("2\n1 1\n2 1\n");
            continue;
        }
        ll sum = 1;
        ll pos = upper_bound(fib,fib+cnt,n)-fib;
        pos--;
        vector <ll> vec;
        for(i = pos;i >= 0;i--)
        {
            if(n >= fib[i])
            {
                vec.push_back(i);
                sum++;
                n -= fib[i];
            }
        }
        printf("%lld\n",sum);
        ll tt = 1,ans = 0;
        for(i = 0;i < vec.size();i++)
        {
            printf("%lld %lld\n",tt,200-vec[i]);
            ans += fib[vec[i]];
            tt += 2;
        }
        printf("%lld %lld\n",tt-1,tt-1);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Ever_glow/article/details/84036527
今日推荐