“玲珑杯”ACM比赛 Round #12 (D) 【矩阵快速幂的时间优化】
//首先,感谢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) 【矩阵快速幂的时间优化】的更多相关文章
- “玲珑杯”ACM比赛 Round #12题解&源码
我能说我比较傻么!就只能做一道签到题,没办法,我就先写下A题的题解&源码吧,日后补上剩余题的题解&源码吧! A ...
- “玲珑杯”ACM比赛 Round #18
“玲珑杯”ACM比赛 Round #18 Start Time:2017-07-15 12:00:00 End Time:2017-07-15 15:46:00 A -- 计算几何你瞎暴力 Time ...
- “玲珑杯”ACM比赛 Round #19题解&源码【A,规律,B,二分,C,牛顿迭代法,D,平衡树,E,概率dp】
A -- simple math problem Time Limit:2s Memory Limit:128MByte Submissions:1599Solved:270 SAMPLE INPUT ...
- “玲珑杯”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 ...
- “玲珑杯”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 ...
- SCUT - 12 - 西方国家 - 矩阵快速幂
https://scut.online/p/12 可以用矩阵快速幂来做. #include<bits/stdc++.h> using namespace std; typedef long ...
- poj 3735 Training little cats 矩阵快速幂+稀疏矩阵乘法优化
题目链接 题意:有n个猫,开始的时候每个猫都没有坚果,进行k次操作,g x表示给第x个猫一个坚果,e x表示第x个猫吃掉所有坚果,s x y表示第x个猫和第y个猫交换所有坚果,将k次操作重复进行m轮, ...
- “玲珑杯”ACM比赛 Round #13 题解&源码
A 题目链接:http://www.ifrog.cc/acm/problem/1111 分析:容易发现本题就是排序不等式, 将A数组与B数组分别排序之后, 答案即N∑i=1Ai×Bi 此题有坑,反正据 ...
- POJ 3735 Training little cats<矩阵快速幂/稀疏矩阵的优化>
Training little cats Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 13488 Accepted: ...
随机推荐
- Java IO流之对象流
对象流 1.1对象流简介 1.2对象流分类 输入流字节流处理流:ObjectInputStream,将序列化以后的字节存储到本地文件 输出流字节流处理流:ObjectOutputStream 1.3序 ...
- Java常用类之【八种基本数据类型】
一.装箱和拆箱 装箱:将基本数据类型包装为对应的包装类对象 拆箱:将包装类对象转换成对应的基本数据类型 JDK5.0中为基本数据类型提供了自动装箱(boxing).拆箱(unboxing)功能 二.八 ...
- STM8程序在IAR中报错 unable to allocate space for sections
Error[Lp011]: section placement failed: unable to allocate space for sections/blocks with a total es ...
- 本地存储 web storage
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Linux系统下源码安装rz/sz命令
背景:在windows环境下,使用xshell远程连接公司内部做的一个类似centos的系统,但该linux系统yum install有问题,只能源码安装. root 账号登陆后,依次执行以下命令: ...
- 【译】Reflection.Emit vs. CodeDOM
原文:http://ayende.com/blog/1606/reflection-emit-vs-codedom Both technologies allow you to generate ex ...
- 详解 try-with-resource
[TOC] Oracle官方文档: http://docs.oracle.com/javase/7/docs/technotes/guides/language/try-with-resources. ...
- 使用dns批量管理普通主机名相关问题
1.dns配置 日常管理主机过程中,会有很多地方需要使用到主机名的,当主机非常多的时候,就不适合使用hosts来管理和同步的所有主机hosts了,这个时候就可以使用dns来管理主机名映射和变动 dns ...
- 【Android Developers Training】 78. 序言:执行网络操作
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- jq-toggle
jq-toggle: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l ...