• 10 25日考试 数学题目练习 斐波拉契 打表


    Time 7:50 AM to 11:15 AM  2016 10 25 AM

    题目:http://files.cnblogs.com/files/CtsNevermore/1025problem.pdf

    试题包:http://files.cnblogs.com/files/CtsNevermore/10-27-16%E5%B9%B410%E6%9C%8825.zip

      据说是数学专题考试,然而最后混进来一个不知道哪来的暴力 + hash,,,都是套路,,,

      个人感觉:1、斐波拉契无比受欢迎= =  2、打表无比重要= =

    解题报告:

      1、看到第一题没什么思路,果断的先打了暴力,然后看着几万行的out文件发呆,果断Get到gcd(f[i], f[j]) = f[gcd(i,j)],看一下数据范围,模数很小不需要高精,直接矩阵快速幂求f[..],本题100分。(某个神奇的eirlys同学迅速发现规律然而不会打矩阵快速幂2333)

    1.	我们先来看看几个有关fibonacci的引理。
    有点难以理解,反正这套题难度是递减的。。。
    
    引理1:
    Gcd(F[n+1],F[n])=1;
    证明:
    根据辗转相减法则
    Gcd(F[n+1],F[n])=Gcd(F[n+1]-F[n],F[n])
                        =Gcd(F[n],F[n-1])
                        =Gcd(F[2],F[1])
    =1
    
    引理2:
    F[m+n]=F[m-1]F[n]+F[m]F[n+1]
    证明:
    F[n+m]=F[n+m-1]+F[n+m-2]
           =2*F[n+m-2]+F[n+m-3]
    =……
    F[n+m]=a[x]*F[n+m-x]+b[x]*F[n+m-x-1];
           =a[x]*(F[n+m-x-1]+F[n+m-x-2])+b[x]*(F[n+m-x-1);
           =(a[x]+b[x])*F[n+m+x-1]+a[x]*F[n+m+x-2];
    当x=1时有 a[1]=F[2];  
    b[1]=F[1];
    当x=2时有 a[2]=F[2]+F[1]=F[3];  
    b[2]=a[1]=F[2];
    当x=k+1时有 a[k+1]=a[k]+b[k]=F[k+1]+F[k]=F[k+2] 
    b[k+1]=a[k]=F[k+1];
    所以当x=n时
    F[n+m]=a[n]F[m]+b[n]F[m-1];
            =F[n+1]F[m]+F[n]F[m-1];
    
    引理3:
    Gcd(F[n+m],F[n])=Gcd(F[n],F[m])
    证明:
    Gcd(F[n+m],F[n])
    =Gcd(F[n+1]F[m]+F[n]F[m-1],F[n]);
    =Gcd(F[n+1]F[m],F[n]);
    =Gcd(F[n+1],F[n])*Gcd(F[m],F[n])
    =Gcd(F[m],F[n]);
    
    由以上三个引理有:Gcd(F[n],F[m])=F[Gcd(n,m)];
    

      以上为证明,反正本菜是没有能力证明,,

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 
     5 const int mod = 19491001;
     6 int n;
     7 int tx, ty;
     8 
     9 struct data {
    10     long long x1, x2, x3, x4;
    11     data (long long x1 = 1, long long x2 = 0, long long x3 = 0, long long x4 = 1) : x1(x1), x2(x2), x3(x3), x4(x4) {};
    12 };
    13 
    14 int gcd(int a, int b) {
    15     if (b == 0) return a;
    16     return (gcd(b, a % b));
    17 }
    18 
    19 data operator * (data a, data b) {
    20     data c;
    21     c.x1 = (a.x1 * b.x1 + a.x2 * b.x3) % mod;
    22     c.x2 = (a.x1 * b.x2 + a.x2 * b.x4) % mod;
    23     c.x3 = (a.x3 * b.x1 + a.x4 * b.x3) % mod;
    24     c.x4 = (a.x3 * b.x2 + a.x4 * b.x4) % mod;
    25     return (c);
    26 }
    27 
    28 data qpow(data x, int v) {
    29     data ans;
    30     while (v > 0) {
    31         if (v & 1) ans = ans * x;
    32         x = x * x;
    33         v >>= 1;
    34     }
    35     return (ans);
    36 }
    37 
    38 int main () {
    39     freopen("fibonacci.in", "r", stdin);
    40     freopen("fibonacci.out", "w", stdout);
    41     scanf("%d", &n);
    42     for (int i = 1; i <= n; i++) {
    43         scanf("%d %d", &tx, &ty);
    44         int ans = gcd(tx, ty);
    45         data cur(0, 1, 1, 1);
    46         cur = qpow(cur, ans-2);
    47         long long tans = ((cur.x2 + cur.x4) % mod + mod) % mod;
    48         printf("%I64d
    ", tans);
    49     }
    50 
    51     return 0;
    52 }

      第一题代码略丑,矩阵乘法一直写得不好看,见谅。

      3、题目描述还算清楚,只是思考黄金分割数取多少时纠结了一下,后来发现取0.618在n较大时毫无意义,开始按照带根号的那个东西来做,第一感觉O(nlog(n))枚举加二分求解,依旧开始打表,偶然发现这些数字有点熟悉,,,好吧又是斐波拉契数,,发现对于一个数n,它的最接近黄金分割数的值为 小于等于它的两个斐波拉契数作比,问题至此圆满解决,,至于证明,,自行百度吧,,

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 
     5 unsigned long long f[100];
     6 unsigned long long n;
     7 
     8 int main () {
     9     freopen("gold.in", "r", stdin);
    10     freopen("gold.out", "w", stdout);
    11     f[1] = 1;
    12     f[2] = 1;
    13     for (int i = 3; i <= 93; i++) f[i] = f[i-1] + f[i-2];
    14     f[94] = 0 - 1;
    15     //for (int i = 1; i <= 94; i++) printf("%I64u
    ", f[i]);
    16     scanf("%I64u", &n);
    17     for (int i = 2; i <= 93; i++) {
    18         if (f[i] <= n && f[i+1] > n) {
    19             printf("%I64u/%I64u", f[i-1], f[i]);
    20         }
    21     }
    22     return 0;
    23 }

      4、考试时打的暴力,还打丑了,,一下子就被zgc拉开了50分,,,-_-,标答如下:首先枚举每一个号码,将它按照题目中所给的允许变化的方案进行变化,将变化结果存在hashtable里,之后利用hash进行判重,如果出现变化后的值与变化前的相同,对两个点进行暴力lcp并连边,最后spfa求解

      代码嘛,,,还没写完= =。。

      2、考试时没看懂题目,,考完后感觉题目描述有问题,总体感觉这题目并不是很可做,,先粘一个题解吧,以后再完善

     1 稍加思索可以发现,行列之间是互不影响的,把每行1的个数看做n堆纸牌、每列1的个数
     2 看做m堆纸牌,题目实际上就是两个环形的均分纸牌问题。 
     3 下面来说环形均分纸牌问题怎么做: 
     4 设有n堆纸牌,每堆有ai张,所有堆一共有S张,那么最终每堆应该有Sn张。因此如果s mod ai≠0,显然是无解的。接下来构造数列bi=ai-sn。 
     5 方法一: 
     6 枚举从第k个位置开始(1=k=n),像均分纸牌的方法一样依次向后推(如果第i 个位置有ai堆牌,那么取bi堆牌分给下一堆,若bi0表示从下一堆拿到这一堆)。最后取最小值。 
     7 时间复杂度O(n^2),预计得分70分。 
     8 方法二: 
     9 设bi的前缀和为si。如果从第k个位置开始,那么第i堆和第i+1堆交换的纸牌数就是  si-sk。总代价就是s1-sk+s2-sk+s3-sk+……+sn-sk。发现什么了?当sk是s1~sn中位数的时候,
    10 上式有最小值!所以把si排序后,令sk=s[(n+1)2],计算代价即可。 
    11 时间复杂度O(nlogn),预计得分100分。
  • 相关阅读:
    C# 正则表达式
    C# 预处理命令
    C# System.Collections
    C#文件流 System.IO和对文件的读写操作
    c# 网站发布
    C# 数据库
    c# 数据存储过程 存储函数
    insert 插入
    SVN远程管理
    【Win】印象笔记快捷键
  • 原文地址:https://www.cnblogs.com/CtsNevermore/p/5997719.html
Copyright © 2020-2023  润新知