zoukankan      html  css  js  c++  java
  • 20161004 NOIP 模拟赛 T1 解题报告

    第1题  小麦亩产一千八

    【问题描述】

         “有了金坷垃,肥料一袋能顶两袋撒,小麦亩产一千八,吸收两米下的氮磷钾……”,话说HYSBZ(Hengyang School for Boys & Zy)学识渊博孩纸们一讲到粮食,都会想起印度那个著名的故事:国王要在第一个格子里放入一粒小麦,接下来的格子放入前面一个格子的两倍的小麦。这样所需小麦总数是巨大的,哪是不用金坷垃就能完成的任务?不过为了减轻国王的任务,那个下棋获胜的宰相换了一个要求:“我只需要你在棋盘外放一粒小麦,可以将其理解为第0个格子,然后你需要在第一个格子里放入若干小麦,之后每一个格子放入前两个格子的小麦数之和的小麦,并且要满足第a个格子放x粒小麦,第b个格子放……”说到这,宰相突然发现自己说的满足第a个格子放x粒小麦的情况可能不存在……欺君可是大罪啊!国王看到宰相迟迟不说,自己也烦了!我自己来算!于是国王拜托你,让你算出第b个格子应该放几粒小麦。当然,就算答案不存在,你也是要告诉国王的。

    【输入格式】kela.in

        该题有多组数据,请读到文件末结束。

    对于每一组数据仅一行,3个正整数a,x,b,分别表示第a个格子放了x粒小麦,以及你所需要计算的是第b个格子的小麦数量。

    【输出格式】kela.out

      对于每一次询问,仅1个整数,为第b个格子的小麦数量,若宰相说的情况不存在,那么请输出-1。

     

    样例输入

    样例输出

    1 1 2
    3 5 4
    3 4 6
    12 17801 19

    2

    8

    -1

    516847

    【样例解释】

        对于样例二,f[1]=2时,能够满足f[3]=5,因此宰相没有撒谎,此时第5个格子的小麦数应为f[4]=f[2]+f[3]=3+5=8.

    数据范围与约定

        对于50%的数据:如果答案存在,那么p<=50

        对于100%的数据:1<=数据组数<=10000,1<=a,b<=20, 数据保证如果答案存在,那么1<=p<=1000000.(注:p是第一格放置的小麦数)。

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

    分析:

      这道题,本蒟蒻只拿到50分(不开森),我果然还是太弱了。

      说说我的暴力思路,二分第一个格子的小麦数(1~1000000),然后取中值,根据这个值递推,这个思路太暴力了(捂脸)。

      下面50分的 暴逆 暴力代码:

     1 #include "cstdio"
     2 
     3 using namespace std ;
     4 const int maxN = 10010 ;
     5 typedef long long QAQ ; 
     6 
     7 QAQ T[ maxN ] ;
     8 
     9 bool Check ( int N , int Target ) {
    10         for ( int i= 2; i<=N ; ++i ) 
    11                 T[ i ] = T [ i - 1] + T[ i - 2 ] ;
    12         
    13         if ( T[ N ] == Target ) return true ;
    14         else                    return false ;
    15 }
    16 
    17 int main ( ) {
    18         QAQ A , B , X ;
    19         bool flag ;
    20         freopen("kela.in","r",stdin);
    21         freopen("kela.out","w",stdout);
    22         while ( scanf( "%I64d%I64d%I64d" , &A , &X , &B ) != EOF ) {
    23                 T[ 0 ] = 1 ;
    24                 int left = 1 , right = 100001 ;
    25                 flag = false ;
    26                 while ( left < right ) {
    27                         int mid = ( left + right ) >> 1 ; 
    28                         T[ 1 ] = mid ;
    29                         if ( Check ( A , X ) )  {
    30                                 flag = true ;
    31                                 break ;
    32                         }
    33                         else if ( T[ A ] > X ) right = mid ;
    34                         else if ( T[ A ] < X ) left = mid + 1 ;
    35                 }
    36                 if ( flag==true ){
    37                         for ( int i=A+1 ; i<=B ; ++i ) T[ i ] = T [ i - 1] + T[ i - 2 ] ;
    38                         printf ( "%I64d
    " , T[ B ] ) ;
    39                 }
    40                 else printf ( "-1
    " ) ;
    41                 
    42         }
    43         fclose(stdin);
    44         fclose(stdout);
    45         return 0 ;
    46 }
    暴力

       AC思路:

      这道题的递推式与Fibonacci数列递推式相同,只是首项不同。那么,这个数列与Fibonacci数列有什么联系?

      设 Fibonacci 数列的每一项为F ( i ) , 即F( 1 ) = 1 , F( 2 ) = 1 , F( 3 ) = 2 , ... ... , F ( n ) = F ( n - 1 ) + F ( n - 2 ) 

      现在要求推出的数列为 f ( i ) , f( 1 ) = 1 , f( 2 ) = p , f( 3 ) = p + 1 , f ( 4 ) = 2 * p + 1  , ... ... , f ( n ) = f ( n - 1 ) + f ( n - 2 ) 

      设 g ( i ) = f ( i ) - F ( i ) ,即 

            g( 1 ) = 0 , g ( 2 ) = p - 1 , g( 3 ) = p - 1 , g( 4 ) = 2 * ( p - 1 )  , g ( 5 ) = 3 * ( p - 1 ) , ... , g ( n ) = F ( n - 1 ) * ( p - 1 ) 

      对于本题  , 已知 f ( a ) = x  , 即

        g ( a ) = f ( a ) - F ( a )  =>  F ( a - 1 ) * ( p - 1 ) = x - F ( a )  

        这道题中 , x已知 , Fibonacci数列又可以通过预处理计算,可以求出 p .

        如果 p 不是整数 , 则输入不合法,直接输出“-1”。

       之后便可以通过递推求得 f ( b ) .

     1 #include "cstdio"
     2 #include "algorithm"
     3 
     4 using namespace std ;
     5 const int INF = 2147483647 ;
     6 typedef long long QAQ ;
     7 
     8 QAQ a,x,b,F[]={0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765};
     9 QAQ f[ 30 ] ;
    10 int main ( ) {
    11         f[ 1 ] = 1 ;
    12         while ( scanf( "%I64d%I64d%I64d" , &a , &x , &b ) == 3 ) {
    13                 x -= F[ a - 1 ] ;
    14                 if ( x % F[ a ] ) {
    15                         printf ( "-1
    ") ;
    16                         continue ;
    17                 }
    18                 else {
    19                         x /= F[ a ] ;
    20                         f[ 2 ] = x  ;
    21                         for ( int i=3 ; i<=b+1 ; ++i ) {
    22                                 f[ i ] = f [ i - 1 ] + f [ i - 2 ] ;
    23                         }
    24                         printf ( "%d
    " , f[ b+1 ] ) ;
    25                 }
    26         }
    27         return 0;
    28 }
    AC

    本蒟蒻要学一点了,NOIP_RP++。

    2016-10-05 00:23:49

     (完)

     

  • 相关阅读:
    动手动脑及类的创建
    动手动脑-Java重载
    方法的动手动脑
    文本单词数测试
    动手动脑
    springmvc使用fastjson
    springmvc之发送json数据自动转Java对象接收
    springmvc之拦截器
    基于xml配置springmvc案例
    springmvc之异常处理
  • 原文地址:https://www.cnblogs.com/shadowland/p/5931470.html
Copyright © 2011-2022 走看看