中南OJ 2012年8月月赛 I题 Imagination

  中南大学OJ 2012年8月月赛,I题,Imagination题目链接)。

Problem I: Imagination

Description

  GBQC国有一个正N边形,各个顶点依次标记为0, 1, …, N-1,小明可以从任意一个顶点开始,每次选择一个未经过的顶点连一条蓝色的线段,然后再以那个点为起点重复以上操作,直到所有的顶点都经过为止。

  那么在最终的画线方案中,各条线段之间不交叉的方案有多少种呢?两条线段不交叉意味着两条线段没有公共点或者公共点均为正N边形的顶点。

Figure 1

  Figure 1描述了N为3时的所有的合法方案。

Figure 2

  Figure 2描述了N为4时的所有的合法方案。

Input

  输入包含多组测试数据。

  每组数据占一行,包含一个正整数N(3 ≤ N ≤ 1018),含义同上。

Output

  对于每组数据用一行输出一个整数,表示在最终的画线方案中,各条线段之间不交叉的方案有多少种。

  由于这个数可能很大,所以你只需要输出这个数除以1000000007所得的余数。

Sample Input

3
4

Sample Output

3
8

Hint

  由于数据量较大,推荐使用scanf和printf。

  解题思路:每次都只向左或右的相邻位置走,否则会把未走过的点划分成两半,导致路线不得不交叉。因此,从某个固定点出发。出最后一条路以外,每个点2个方向,即为 \( \displaystyle\underbrace{2\times2\times\cdots\times2}_{n-2 \, 个\, 2}\) ,即2n-2。一共有n个点,所以乘以n。由于是无向图,因此“A为起点,B为终点”和“B为起点,A为终点”是一样的,所以最终答案要除以2,即为 \( \displaystyle\frac{2^{n-2}\, \cdot \, n}{2} = 2^{n-3} \cdot n \) 。但是n很大,所以要用快速幂来搞。

  C++语言源代码如下:

#include <cstdio>
#include <cstdlib>

using namespace std;

const long long MOD_NUM = 1000000007; 

inline long long power2( long long n )
{
    long long result = 1;
    long long partial_result = 2;
    while( n )
    {
        if ( (n % 2) == 1 )
        {
            result *= partial_result ;
            result %= MOD_NUM;
        }
        partial_result = partial_result * partial_result;
        partial_result %= MOD_NUM;
        n /= 2;
    }
    return result;
}   

inline long long calc( const long long & n )
{
    return ( power2( n-3 ) * (n % MOD_NUM) ) % MOD_NUM ;
}

int main (void)
{
    long long n;
    while ( scanf( "%lld", &n ) != EOF )
        printf( "%lld\n", calc(n) );
    return EXIT_SUCCESS;
}
posted @ 2012-08-12 21:40  叶剑飞Victor  阅读(554)  评论(0编辑  收藏  举报