//首先,感谢Q巨

题目链接

定义状态向量b[6]

  b[0]:三面临红色的蓝色三角形个数

  b[1]:两面临红色且一面临空的蓝色三角形个数

  b[2]:一面临红色且两面临空的蓝色三角形个数

  b[3]:三面临红色的黄色三角形个数

  b[4]:两面临红色且一面临绿+的黄色三角形个数

  b[5]:一面临红色且两面临绿+的黄色三角形个数

转移矩阵:

[3 1 0 0 0 0;
0 2 2 0 0 0;
0 1 3 0 0 0;
3 2 1 0 0 0;
0 0 0 6 3 0;
0 0 0 0 2 4]

最朴素的TLE代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
;
;
LL b[N]= {,,,,,};        //此处初始化列向量
LL hh[N][N]={{,,,,,},
             {,,,,,},
             {,,,,,},
             {,,,,,},
             {,,,,,},
             {,,,,,}
            };
struct Mat
{
    LL mat[N][N];
} A;
Mat Mut(Mat a,Mat b)
{
    Mat c;
    memset(c.mat,,sizeof(c.mat));
    ; k<N; k++)
        ; i<N; i++)
            if(a.mat[i][k])
            ; j<N; j++)
            {
                c.mat[i][j]+=a.mat[i][k]*b.mat[k][j]%mod;
                c.mat[i][j]=c.mat[i][j]%mod;
            }
    return c;
}
Mat Qpow(Mat a,LL n)
{
    Mat c;
    ; i<N; ++i)
        ; j<N; ++j)
            c.mat[i][j]=(i==j);
    )
    {
        ) c=Mut(c,a);
        a=Mut(a,a);
    }
    return c;
}
void cal(Mat A,LL n,LL b[],LL& Fn,LL& Gn)
{
    Mat A_=Qpow(A,n-);
    Fn=Gn=;
    LL c[N]={};
    ;i<N;i++)
        ;j<N;j++)
            c[i]=(c[i]+A_.mat[i][j]*b[j])%mod;
    Fn=(c[]+c[]+c[])%mod;
    Gn=(c[]+c[]+c[])%mod;
}
void init_A()
{
    ;i<N;i++)
        ;j<N;j++)
            A.mat[i][j]=hh[i][j];
}

int main()
{
    LL n,Fn,Gn;
    init_A();
    while(cin>>n)
    {
        )
        {
            puts("1 0");
            continue;
        }
        n--;
        cal(A,n,b,Fn,Gn);
        cout<<Fn<<' '<<Gn<<endl;
    }
}

貌似(只是貌似)被优化但仍然TLE的代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
;
;
LL b[N]= {,,,,,};        //此处初始化列向量
LL hh[N][N]={{,,,,,},
             {,,,,,},
             {,,,,,},
             {,,,,,},
             {,,,,,},
             {,,,,,}
            };
struct Mat
{
    LL mat[N][N];
} A,F[];
void printM(Mat x)
{
    puts("=================================================================");
    ;i<N;i++)
    {
        ;j<N;j++)
            printf("%10lld",x.mat[i][j]);
        puts("");
    }
}
Mat Mut(Mat a,Mat b)
{
    Mat c;
    memset(c.mat,,sizeof(c.mat));
    ; k<N; k++)
        ; i<N; i++)
            if(a.mat[i][k])
            ; j<N; j++)
            {
                c.mat[i][j]+=a.mat[i][k]*b.mat[k][j]%mod;
                c.mat[i][j]=c.mat[i][j]%mod;
            }
    return c;
}

Mat Qpow(Mat a,LL n)
{
    Mat c;
    ; i<N; ++i)
        ; j<N; ++j)
            c.mat[i][j]=(i==j);
    )
    {
        ) c=Mut(c,a);
        a=Mut(a,a);
    }
    return c;
}
void cal(Mat A,LL n,LL b[],LL& Fn,LL& Gn)
{
    Mat A_;
    ; i<N; ++i)
        ; j<N; ++j)
            A_.mat[i][j]=(i==j);
    ;i<&&n;i++,n>>=)
        ) A_=Mut(A_,F[i]);
    //printM(A_);
    Fn=Gn=;
    LL c[N]={};
    ;i<N;i++)
        ;j<N;j++)
            c[i]=(c[i]+A_.mat[i][j]*b[j])%mod;
    Fn=(c[]+c[]+c[])%mod;
    Gn=(c[]+c[]+c[])%mod;
}

void init_A()
{
    ;i<N;i++)
        ;j<N;j++)
            A.mat[i][j]=hh[i][j];
    F[]=A;
    ;i<;i++)
        F[i]=Mut(F[i-],F[i-]);
}

int main()
{
    LL n,Fn,Gn;
    init_A();
    int T;
//    cin>>T;
    scanf("%lld",&T);
    while(T--)
    {
//        cin>>n;
        scanf("%lld",&n);
        )
        {
            puts("1 0");
            continue;
        }
        n-=;
        cal(A,n,b,Fn,Gn);       //        cout<<Fn<<' '<<Gn<<endl;
        printf("%lld %lld\n",Fn,Gn);
    }
}

矩阵相乘一次的复杂度是O(N^3)的,不过预处理2^i(i:0~60)的矩阵后,可以用向量记录中间结果,而矩阵*向量的复杂度为O(N^2)

最终复杂度: O(T * lb(n) * N^2)->O(1e5 * 60 * 36)->O(2e8)

最终可以AC的代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
;
;
LL b[N]= {,,,,,};        //此处初始化列向量
LL hh[N][N]={{,,,,,},
             {,,,,,},
             {,,,,,},
             {,,,,,},
             {,,,,,},
             {,,,,,}
            };
struct Mat
{
    LL mat[N][N];
} A,F[];
void printM(Mat x)
{
    puts("=================================================================");
    ;i<N;i++)
    {
        ;j<N;j++)
            printf("%10lld",x.mat[i][j]);
        puts("");
    }
}
Mat Mut(Mat a,Mat b)
{
    Mat c;
    memset(c.mat,,sizeof(c.mat));
    ; k<N; k++)
        ; i<N; i++)
            if(a.mat[i][k])
            ; j<N; j++)
            {
                c.mat[i][j]+=a.mat[i][k]*b.mat[k][j]%mod;
                c.mat[i][j]=c.mat[i][j]%mod;
            }
    return c;
}

Mat Qpow(Mat a,LL n)
{
    Mat c;
    ; i<N; ++i)
        ; j<N; ++j)
            c.mat[i][j]=(i==j);
    )
    {
        ) c=Mut(c,a);
        a=Mut(a,a);
    }
    return c;
}
void cal(Mat A,LL n,LL b[],LL& Fn,LL& Gn)
{
    Mat A_;
    LL c[N]={,,,,,};
    ; i<N; ++i)
        ; j<N; ++j)
            A_.mat[i][j]=(i==j);
    ;i<&&n;i++,n>>=)
        )
        {
            LL tres[]={,,,,,};
            ;j<;j++)    //矩阵的行
                ;k<;k++)    //矩阵的列
                    tres[j]=(tres[j]+F[i].mat[j][k]*c[k])%mod;
            ;j<;j++)
                c[j]=tres[j]%mod;
        }
    Fn=Gn=;
    Fn=(c[]+c[]+c[])%mod;
    Gn=(c[]+c[]+c[])%mod;
}

void init_A()
{
    ;i<N;i++)
        ;j<N;j++)
            A.mat[i][j]=hh[i][j];
    F[]=A;
    ;i<;i++)
        F[i]=Mut(F[i-],F[i-]);
}

int main()
{
    LL n,Fn,Gn;
    init_A();
    int T;
    scanf("%lld",&T);
    while(T--)
    {
        scanf("%lld",&n);
        )
        {
            puts("1 0");
            continue;
        }
        n-=;
        cal(A,n,b,Fn,Gn);
        printf("%lld %lld\n",Fn,Gn);
    }
}

“玲珑杯”ACM比赛 Round #12 (D) 【矩阵快速幂的时间优化】的更多相关文章

  1. “玲珑杯”ACM比赛 Round #12题解&源码

    我能说我比较傻么!就只能做一道签到题,没办法,我就先写下A题的题解&源码吧,日后补上剩余题的题解&源码吧!                                     A ...

  2. “玲珑杯”ACM比赛 Round #18

    “玲珑杯”ACM比赛 Round #18 Start Time:2017-07-15 12:00:00 End Time:2017-07-15 15:46:00 A -- 计算几何你瞎暴力 Time ...

  3. “玲珑杯”ACM比赛 Round #19题解&源码【A,规律,B,二分,C,牛顿迭代法,D,平衡树,E,概率dp】

    A -- simple math problem Time Limit:2s Memory Limit:128MByte Submissions:1599Solved:270 SAMPLE INPUT ...

  4. “玲珑杯”ACM比赛 Round #19 B -- Buildings (RMQ + 二分)

    “玲珑杯”ACM比赛 Round #19 Start Time:2017-07-29 14:00:00 End Time:2017-07-29 16:30:00 Refresh Time:2017-0 ...

  5. “玲珑杯”ACM比赛 Round #1

    Start Time:2016-08-20 13:00:00 End Time:2016-08-20 18:00:00 Refresh Time:2017-11-12 19:51:52 Public ...

  6. SCUT - 12 - 西方国家 - 矩阵快速幂

    https://scut.online/p/12 可以用矩阵快速幂来做. #include<bits/stdc++.h> using namespace std; typedef long ...

  7. poj 3735 Training little cats 矩阵快速幂+稀疏矩阵乘法优化

    题目链接 题意:有n个猫,开始的时候每个猫都没有坚果,进行k次操作,g x表示给第x个猫一个坚果,e x表示第x个猫吃掉所有坚果,s x y表示第x个猫和第y个猫交换所有坚果,将k次操作重复进行m轮, ...

  8. “玲珑杯”ACM比赛 Round #13 题解&源码

    A 题目链接:http://www.ifrog.cc/acm/problem/1111 分析:容易发现本题就是排序不等式, 将A数组与B数组分别排序之后, 答案即N∑i=1Ai×Bi 此题有坑,反正据 ...

  9. POJ 3735 Training little cats<矩阵快速幂/稀疏矩阵的优化>

    Training little cats Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 13488   Accepted:  ...

随机推荐

  1. nodeJS之TCP模块net

    前面的话 TCP服务在网络应用中十分常见,目前大多数的应用都是基于TCP搭建而成的.net模块提供了一个异步网络包装器,用于TCP网络编程,它包含了创建服务器和客户端的方法.本文将详细介绍nodeJS ...

  2. 一般处理程序+htm C#l简单的增删查改

    首先引用两个文件一个dll: 数据库表已创建 首先编写数据读取部分 /// <summary> /// 查询 /// </summary> /// <param name ...

  3. C语言到C++(1) - 基本变化

    说到C++和C语言的区别,大部分人都会想到面向对象和面向过程.然而这种说法并不准确.面向对象和面向过程指的是两种不同的程序设计思想,而C++与C是两种编程语言,难道C++就不能用于面向过程去解决问题吗 ...

  4. 利用npm安装/删除/发布/更新/撤销发布包 --社会我npm哥,好用话不多

      一.什么是npm? npm是javascript的包管理工具,是前端模块化下的一个标志性产物 简单地地说,就是通过npm下载模块,复用已有的代码,提高工作效率   1.从社区的角度:把针对某一特定 ...

  5. 关于cas server无法通过session持久化方式实现集群的问题

    最近在搭建cas单点登录系统 ,在建立集群时发生一个问题. 搭建的环境是tomcat+tomcat-redis-session-manager+redis+cas 在对tomcat的session进行 ...

  6. node.js零基础详细教程(4):node.js事件机制、node异步IO操作

    第四章 建议学习时间3小时  课程共10章 学习方式:详细阅读,并手动实现相关代码 学习目标:此教程将教会大家 安装Node.搭建服务器.express.mysql.mongodb.编写后台业务逻辑. ...

  7. HTML5 Web Worker简单使用

    Web Workers 是 HTML5 提供的一个javascript多线程解决方案,我们可以将一些大计算量的代码交由web Worker运行而不冻结用户界面. 一:如何使用Worker Web Wo ...

  8. 【VC6.0】getline需要输入2次回车才会结束的BUG修复方法

    原始日期:2013-09-30 23:22 今天看C++Primer的时候发现一个问题,getline需要输入2次回车才会显示结果,上网找了一下,发现是VC6.0的原因,修复原因如下: (1)建立一个 ...

  9. 愚公oracle数据库同步工具

    最近,利用一些时间对oracle数据库实时同步工具做了一些调研分析,主要关注了linkedin的databus和阿里的yugong两个中间件,其中databus需要在每个待同步的表上增加额外的列和触发 ...

  10. git视频教程

    git 精简版视频教程-2小时快速入门精华版,小教程很快就可以看完. 旺旺 QQ:Git是目前世界上最先进的分布式版本控制系统(没有之一). Git有非常高的逼格,简单来说就是:高端大气上档次. 这么 ...