NOIP欢乐模拟赛 T2 解题报告

小澳的坐标系

coordinate.cpp/c/pas

题目描述

小澳者表也,数学者景也,表动则景随矣。

小澳不喜欢数学,可数学却待小澳如初恋,小澳睡觉的时候也不放过。

小澳的梦境中出现了一个平面直角坐标系,自原点,向四方无限延伸。

小澳在坐标系的原点,他可以向上、向左或者向右走。他可以走n步,但不能经过相同的点

小澳想知道他有多少种走法。

 

输入格式

输入文件名为coordinate.in。

输入文件仅第一行一个正整数n,表示小澳可以走的步数。

 

输出格式

输出文件名为coordinate.out。

输出文件共一行,输出一个正整数,表示答案(对10^9+7取模)。

 

输入输出样例1

coordinate.in

coordinate.out

2

7

 

【输入输出样例1说明】

从(0,0)出发走2步,共7种走法:

(0,0)->(0,1)->(0,2)

(0,0)->(0,1)->(1,1)

(0,0)->(0,1)->(-1,1)

(0,0)->(1,0)->(2,0)

(0,0)->(1,0)->(1,1)

(0,0)->(-1,0)->(-2,0)

(0,0)->(-1,0)->(-1,1)

 

输入输出样例2

coordinate.in

coordinate.out

3

17

 

 

数据规模与约定

测试点编号

n

1~2

n<=10

3~4

n<=100

5~6

n<=1000

7~8

n<=10^6

9~10

n<=10^9

 

————————————————————————分割线————————————————————————

分析:

看到这道题不难想到他的递推式

在上图,蓝点表示只有两种走法的点,红点表示三种走法的点,红蓝相间表示两种都有。

普通递推式如下 ( 80分 ):

F[i][0]=F[i-1][0]+F[i-1][1]*2

F[i][1]=F[i-1][0]+F[i-1][1] 

 

 1 #include "bits/stdc++.h"
 2 
 3 using namespace std ;
 4 typedef long long QAQ ;
 5 const int MOD = 1e9 + 7 ;
 6 
 7 int main ( ) {
 8         QAQ t1 = 1 , t2 = 3 , t3 = 3 , N ;
 9         cin >> N ;
10         --N ;
11         for ( int i=1 ; i<=N ; ++i ) {
12                 t3 = ( t2 - t1 ) * 2 + t1 * 3 ;
13                 t1 = t2 ;
14                 t2 = t3 ;
15         }    
16         cout << t3 << endl ;
17         return 0 ;
18 }
View Code

 

但是,我们发现每一步只与上一步有关,可以建立递推关系,构造矩阵+快速幂解决。( AC )

 

 

 1 #include "bits/stdc++.h"
 2  
 3 using namespace std;
 4 typedef long long QAQ ;
 5 const int MOD = 1e9 + 7 ;
 6 
 7 struct Matrix{
 8         QAQ v[2][2];
 9         Matrix ( ) { memset ( v , 0 , sizeof ( v ) ) ; }
10 }base , ans ;
11 
12 Matrix operator*( Matrix x , Matrix y ) {
13         Matrix res;
14         for(int i=0;i<2;i++)
15         for(int j=0;j<2;j++)
16         for(int k=0;k<2;k++)
17                 (res.v[i][j]+=(x.v[i][k]*y.v[k][j]%MOD))%=MOD;
18         return res;
19 }
20 
21 int main ( ) {
22         int N ;
23         scanf ( "%d" , &N ) ; 
24         ans.v[ 0 ][ 0 ] = 1 ;
25         base.v[ 0 ][ 0 ] = base.v[ 0 ][ 1 ] = base.v[ 1 ][ 1 ] = 1 ;
26         base.v[ 1 ][ 0 ] = 2 ;
27         for ( int i=N + 1 ; i ; i>>=1 , base = base * base )
28                 if  ( i & 1 ) ans = ans * base ;
29         printf( "%I64d\n" , ans.v[0][0] ) ;
30         return 0 ;
31 }
Matrix

2016-10-03 21:42:08 

 PS:本题可以进一步化简递推,可得 f ( n ) = 2 * f ( n - 1 ) + f ( n - 2 ) ,也可得到答案。

(完)

 

转载于:https://www.cnblogs.com/shadowland/p/5929581.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
NOI(全国青少年信息学奥林匹克竞模拟的测试数据是指用于评测参选手的程序的输入和对应的输出。测试数据是非常重要的,因为它决定了参选手的程序能否正确地解决问题。 在NOI模拟中,测试数据具有以下特点: 1.充分覆盖:测试数据应涵盖各种可能的输入情况,包括边界条件和极端情况。通过提供不同的测试数据,可以考察选手对问题的全面理解和解决能力。 2.随机性和均衡性:为了公平起见,测试数据应该是随机生成的,而不是针对某个特定算法或解法设计的。同时,测试数据应该是均衡的,即各种情况的概率应该大致相等,以避免偏向某些解法。 3.合理性和可行性:测试数据应该是合理和可行的,即符合题目要求的输入数据,并且是选手能够通过编写程序来处理的。测试数据应该考虑到程序的限制和时间复杂度,以充分测试选手的编程能力。 NOI模拟的测试数据通常由经验丰富的考题组负责生成。他们会根据题目的要求和限制,设计出一组合理、充分、随机和均衡的测试数据,以确保参选手的程序在各种情况下都能正确运行,并且能通过性能测试。 总之,测试数据在NOI模拟中起到了至关重要的作用,它既考察了选手对问题的理解和解决能力,又提高了选手编程的技巧和效率。同时,合理和恰当的测试数据也是公平竞的保证,确保每个参选手有相同的机会和条件进行竞争。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值