zoukankan      html  css  js  c++  java
  • 【JZOJ4854】【NOIP2016提高A组集训第6场11.3】小澳的坐标系

    题目描述

    小澳者表也,数学者景也,表动则景随矣。
    小澳不喜欢数学,可数学却待小澳如初恋,小澳睡觉的时候也不放过。
    小澳的梦境中出现了一个平面直角坐标系,自原点,向四方无限延伸。
    小澳在坐标系的原点,他可以向上、向左或者向右走。他可以走n步,但不能经过相同的点。
    小澳想知道他有多少种走法。

    数据范围测试点

    1~2
    n<=10
    测试点3~4
    n<=100
    测试点5~6
    n<=1000
    测试点7~8
    n<=10^6
    测试点9~10
    n<=10^9

    解法

    设f[i]为输入为i时,答案为f[i],设g[i]=f[i+1]-f[i]。
    找规律获得g[i]=2*g[i-1]+g[i-2]。
    矩阵乘法优化即可。


    理性解法:
    设f[i]为第i步走左的方案数,g[i]为第i步往右走的方案数,h[i]为第i步往上走的方案数;
    显然:

    f[i]=f[i1]+h[i1],g[i]=g[i1]+h[i1],h[i]=f[i1]+h[i1]+g[i1]

    矩阵乘法优化即可。

    代码

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const char* fin="coordinate.in";
    const char* fout="coordinate.out";
    const ll inf=0x7fffffff;
    const ll maxn=4,mo=1000000007;
    ll n,i,j,k;
    struct rect{
        ll d[maxn][maxn];
        rect(){
            memset(d,0,sizeof(d));
        }
        void operator =(const rect &b){
            ll i,j,k;
            for (i=0;i<maxn;i++) for (j=0;j<maxn;j++) d[i][j]=b.d[i][j];
        }
        rect operator *(const rect &b){
            rect c;
            ll i,j,k;
            for (i=0;i<maxn;i++)
                for (j=0;j<maxn;j++)
                    for (k=0;k<maxn;k++){
                        c.d[i][j]=(c.d[i][j]+d[i][k]*b.d[k][j])%mo;
                    }
            return c;
        }
    
    }a,b,ans;
    rect power(rect a,ll v){
        rect c;
        bool bz=false;
        while (v){
            if (v&1){
                if (!bz) c=a,bz=true;
                else c=c*a;         
            }
            a=a*a;
            v>>=1;
        }
        return c;
    }
    int main(){
        freopen(fin,"r",stdin);
        freopen(fout,"w",stdout);
        scanf("%lld",&n);
        if (n==0) printf("1");
        else if (n==1) printf("3");
        else if (n==2) printf("7");
        else{
            a.d[0][0]=7;a.d[0][1]=3;a.d[0][2]=4;a.d[0][3]=2;
            b.d[0][0]=b.d[0][1]=b.d[2][3]=b.d[3][0]=b.d[3][2]=1;
            b.d[2][0]=b.d[2][2]=2;
            a=a*power(b,n-2);
            printf("%lld",a.d[0][0]);
        }
        return 0;
    }

    启发

    观察题目得,当前方案数肯定由上一步的方案数得出。
    尝试写出动态规划方程式,然后进行矩阵乘法优化邻近状态转移。

  • 相关阅读:
    B树,B+树比较
    Kafka、RabbitMQ、RocketMQ 全方位对比
    ElasticSearch 笔记
    AtomicReference实现单例模式
    Netty 核心组件笔记
    Netty Reactor 线程模型笔记
    urldecode和urlencode相互转换
    python字符格式问题SyntaxError: Non-UTF-8 code starting with 'xe4'
    百度文字识别获取access token
    Python中MD5加密
  • 原文地址:https://www.cnblogs.com/hiweibolu/p/6714853.html
Copyright © 2011-2022 走看看