zoukankan      html  css  js  c++  java
  • HDU 2256 Problem of Precision(矩阵高速幂)

    题目地址:HDU 2256

    思路:

    (sqrt(2)+sqrt(3))^2*n=(5+2*sqrt(6))^n;

    这时要注意到(5+2*sqrt(6))^n总能够表示成an+bn*sqrt(6);

    an+bn*(sqrt(6))=(5+2*sqrt(6))*(a(n-1)+b(n-1)*sqrt(6))

                            =(5*a(n-1)+12*b(n-1))+(2*a(n-1)+5*b(n-1))*sqrt(6);

    显然,an=5*a(n-1)+12*b(n-1);bn=2*a(n-1)+5*b(n-1);

    此时能够非常easy的构造出一个矩阵来高速求an和bn:

    5,12

    2,5

    那么下一步应该怎么办呢?对于我等菜渣来说最好的办法当然是。。打表。。找规律。。

    然后规律就是ans=2*an-1;

    那么怎么证明呢?证明例如以下:

    (5+2*sqrt(6))^n=an+bn*sqrt(6);  (5-2*sqrt(6))^n=an-bn*sqrt(6);

    (5+2*sqrt(6))^n+(5-2*sqrt(6))^n=2*an;

    然后,因为

    (5-2*sqrt(6))^n=(0.101....)^n<1;

    再因为

    (5+2*sqrt(6))^n=2*an-(5-2*sqrt(6))^n

    可得

    2*an-1<(5+2*sqrt(6))^n<2*an;

    所以对(5+2*sqrt(6))^n向下取整的结果一定是2*an-1;

    证明完成。

    所以说仅仅要用矩阵高速幂求出an就可以。

    代码例如以下:

    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <stdlib.h>
    #include <math.h>
    #include <ctype.h>
    #include <queue>
    #include <map>
    #include <set>
    #include <algorithm>
    
    using namespace std;
    const int mod=1024;
    struct matrix
    {
        int ma[3][3];
    }init, res;
    matrix Mult(matrix x, matrix y)
    {
        matrix tmp;
        int i, j, k;
        for(i=0;i<2;i++)
        {
            for(j=0;j<2;j++)
            {
                tmp.ma[i][j]=0;
                for(k=0;k<2;k++)
                {
                    tmp.ma[i][j]=(tmp.ma[i][j]+x.ma[i][k]*y.ma[k][j])%mod;
                }
            }
        }
        return tmp;
    }
    matrix Pow(matrix x, int k)
    {
        int i, j;
        matrix tmp;
        for(i=0;i<2;i++) for(j=0;j<2;j++) tmp.ma[i][j]=(i==j);
        while(k)
        {
            if(k&1) tmp=Mult(tmp,x);
            x=Mult(x,x);
            k>>=1;
        }
        return tmp;
    }
    int main()
    {
        int t, k;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&k);
            init.ma[0][0]=5;
            init.ma[0][1]=12;
            init.ma[1][0]=2;
            init.ma[1][1]=5;
            res=Pow(init,k-1);
            int ans=(2*(res.ma[0][0]*5+res.ma[0][1]*2)-1)%mod;
            printf("%d
    ",ans);
        }
        return 0;
    }
    


  • 相关阅读:
    【c++】重载操作符
    关于Repository模式
    UML建模系列文章总结
    windows批量创建用户
    数据库数据导入导出系列之五 C#实现动态生成Word(转)
    C#.bat文件清理工程目录
    ASP.NET用HttpListener实现文件断点续传
    LINQ to JavaScript
    依赖注入框架Autofac的简单使用
    spring boot日期转换
  • 原文地址:https://www.cnblogs.com/llguanli/p/6723868.html
Copyright © 2011-2022 走看看