zoukankan      html  css  js  c++  java
  • BZOJ 2973 石头游戏 矩乘加速递推

    FFFFFFF,看了一上午才看懂,又调了一中午。。。。。我终于明白为何自己如此菜了qwq


    这个题加速的思路是:因为每个序列的长度小于6,他们的lcm是60,所以六十次以后就会回到原来的序列。

    加速的就是这一个个重复的60次

    我们把60个转移矩阵乘起来(结合律),设为d,然后有x=t/60就是有多少个d,算出d的x次方(快速幂)

    然后不足60次的一个个乘起来就好了

    至于如何建转移矩阵。。。模拟一下吧(我搞了一上午qwq):

    e[k]是第k次的转移矩阵,取石子从0里面取(因此e[k][0][0]都是1)

    对于这个矩阵,可以理解为 e[第k次][从哪个状态来][到哪个状态去]

    因为矩阵乘不就是ret[i][j]+=a[i][k]*b[k][j],其中b就是转移矩阵(再不理解可以吧i那一维给去了)

    PS:sizeof时注意是指针的大小还是数组的大小。。。因为这个调了一中午。。。。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define ll long long
    #define R register int
    using namespace std;
    inline ll g() {
        register ll ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
        do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
    }
    int n,m,t,p,q;
    int a[20][20],cnt[20][20];
    ll f[70],d[70][70],e[70][70][70];
    ll ans;
    char b[20][20],s[100],ch;
    inline int pos(int i,int j) {return (i-1)*m+j;}
    inline ll max(ll a,ll b) {return a>b?a:b;}
    // inline void print(ll *a) { cout<<endl<<"fasdfas"; //调试输出
    //     for(R i=0;i<=p;++i) printf("%lld ",a[i]); cout<<endl;
    // }
    // inline void print2(ll a[70][70]) { cout<<"eeewee";
    //     for(R i=0;i<=p;++i,cout<<endl<<"      ") for(R j=0;j<=p;++j) printf("%lld ",a[i][j]);
    // }
    inline void mul1(ll a[70][70],ll b[70][70]) {
        register ll ret[70][70]; memset(ret,0,sizeof(ret));
        for(R i=0;i<=p;++i) for(R k=0;k<=p;++k) if(a[i][k]) for(R j=0;j<=p;++j)
            ret[i][j]+=a[i][k]*b[k][j];
        memcpy(a,ret,sizeof(ret));
    }
    inline void mul2(ll f[70],ll a[70][70]) {
        register ll ret[70]; memset(ret,0,sizeof(ret));
        for(R j=0;j<=p;++j) for(R k=0;k<=p;++k) 
            ret[j]+=f[k]*a[k][j];
        memcpy(f,ret,sizeof(ret));
    }
    inline void build() {
        for(R k=1;k<=60;e[k][0][0]=1,++k) for(R i=1;i<=n;++i) for(R j=1;j<=m;++j) {
            R x=a[i][j],p=cnt[i][j]; 
            if(b[x][p]>='0'&&b[x][p]<='9') {
                e[k][0][pos(i,j)]=b[x][p]-'0';
                e[k][pos(i,j)][pos(i,j)]=1;
            } else if(b[x][p]=='N'&&i>1) e[k][pos(i,j)][pos(i-1,j)]=1;
            else if(b[x][p]=='W'&&j>1) e[k][pos(i,j)][pos(i,j-1)]=1;
            else if(b[x][p]=='S'&&i<n) e[k][pos(i,j)][pos(i+1,j)]=1;
            else if(b[x][p]=='E'&&j<m) e[k][pos(i,j)][pos(i,j+1)]=1;
            cnt[i][j]=(p+1)%strlen(b[x]);
        } if(t>60) {memcpy(d,e[1],sizeof(e[1])); for(R i=2;i<=60;++i) mul1(d,e[i]);}
    }
    signed main() {
        n=g(),m=g(),t=g(),q=g(); p=n*m;
        for(R i=1;i<=n;++i) {
            scanf("%s",s+1); 
            for(R j=1;j<=m;++j) ch=s[j],a[i][j]=(ch^48)+1;
        } for(R i=1;i<=q;++i) scanf("%s",&b[i]);
        build(); f[0]=1; 
        for(R i=t/60;i;i>>=1,mul1(d,d)) if(i&1) mul2(f,d);
        for(R i=1,lim=t%60;i<=lim;++i) mul2(f,e[i]);
        for(R i=1;i<=p;++i) ans=max(ans,f[i]); printf("%lld
    ",ans); 
        //while(1);
    }

    别颓废,至少看起来你懂了。2019.05.10

  • 相关阅读:
    Python Django :HTTP生命周期
    Docker简介及Centos 7 安装[初步配置]
    python:Django 简介。
    python :Django url /views /Template 文件介绍
    python:异常处理及程序调试
    python之正则表达式【re】
    Day 21 python :面向对象 类的相关内置函数 /单例模式 /描述符
    Day 22: 软件开发目录设计规范
    Day 20: 面向对象【多态,封装,反射】字符串模块导入/内置attr /包装 /授权
    SpringCloud教程 | 第九篇: 服务链路追踪(Spring Cloud Sleuth)
  • 原文地址:https://www.cnblogs.com/Jackpei/p/10844047.html
Copyright © 2011-2022 走看看