COI 2020 Semafor

题目大意

  • 给定一个初始显示XXX的MMM位的五段显示器,求NNN次操作后显示为i(i∈[0,10M))i(i\in[0,10^M))i(i∈[0,10M))的方案数,需满足每KKK次操作后显示的均是一个合法的数字。每次操作即改变显示器某一段的开关状态。
  • M≤2,N≤1015M\le 2,N\le 10^{15}M≤2,N≤1015

题解

  • 看到多次操作后求方案数会想到矩乘,为了满足KKK的限制,可以先把每操作KKK次后的状态计算出来,如果不是合法的数的状态则忽略,再计算NK\frac{N}{K}KN​ 次合法的数之间的转移,最后再算上剩下Nmod⁡KN\operatorname{mod}KNmodK 次操作。
  • 计算一下复杂度,合法的数之间的转移最大是1023∗log⁡N=106∗log⁡N{10^2}^3*\log N = 10^6 * \log N1023∗logN=106∗logN,但前面每KKK次所有状态之间的转移,当M=2M=2M=2时显示器有十段,状态压缩后大小为210=10242^{10}=1024210=1024,矩乘转移的复杂度一次就是(210)3=230(2^{10})^3=2^{30}(210)3=230,显然需要改变做法。
  • 可以发现,当合法的两个数x,yx,yx,y之间的转移,相当于把某些位取反,而剩下的不变,即异或上某数k=xxor⁡yk=x\operatorname{xor}yk=xxory。那么对固定的kkk,任意xxx转移到xxor⁡kx\operatorname{xor} kxxork的方案数都相等,所以转移矩阵就不需要维护210∗2102^{10}*2^{10}210∗210大小,而只需记录不同的转移kkk的值。
  • 转移时直接枚举iii和jjj转移到ixor⁡ji\operatorname{xor}jixorj即可。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define md 1000000007
#define N 1100
#define M 110
int p[10] = {10, 2, 9, 7, 18, 21, 12, 3, 29, 23};
int vi[N];
ll d[M], ans[M];
ll f[M][M], g[M][M], c[M][M], cc[M][M];
ll F[N], G[N], C[N];
void ksm(ll x, int n) {if(!x) {for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) f[i][j] = (i == j);}else {ksm(x / 2, n);for(int i = 0; i < n; i++)for(int j = 0; j < n; j++) g[i][j] = 0;for(int i = 0; i < n; i++)for(int k = 0; k < n; k++) if(f[i][k])for(int j = 0; j < n; j++) g[i][j] = (g[i][j] + f[i][k] * f[k][j]) % md;for(int i = 0; i < n; i++)              for(int j = 0; j < n; j++) f[i][j] = g[i][j];if(x % 2) {for(int i = 0; i < n; i++)for(int j = 0; j < n; j++) g[i][j] = 0;for(int i = 0; i < n; i++)for(int k = 0; k < n; k++) if(c[i][k])for(int j = 0; j < n; j++) g[i][j] = (g[i][j] + c[i][k] * f[k][j]) % md;for(int i = 0; i < n; i++)               for(int j = 0; j < n; j++) f[i][j] = g[i][j];}}
}
void Ksm(ll x, int n) {if(!x) {for(int i = 0; i < n; i++) F[i] = (i == 0);}else {Ksm(x / 2, n);for(int i = 0; i < n; i++) G[i] = 0;for(int i = 0; i < n; i++) if(F[i])for(int j = 0; j < n; j++) G[i ^ j] = (G[i ^ j] + F[i] * F[j]) % md;for(int i = 0; i < n; i++) F[i] = G[i];if(x % 2) {for(int i = 0; i < n; i++) G[i] = 0;for(int i = 0; i < n; i++) if(C[i])for(int j = 0; j < n; j++) G[i ^ j] = (G[i ^ j] + C[i] * F[j]) % md;for(int i = 0; i < n; i++) F[i] = G[i];}}
}
int main() {ll n, K;int m, X, i, j, k;scanf("%d%lld%lld%d", &m, &n, &K, &X);if(m == 1) {for(i = 0; i < 5; i++) C[1 << i] = 1;Ksm(K, 32);memset(vi, 255, sizeof(vi));for(i = 0; i < 10; i++) vi[p[i]] = i;for(i = 0; i < 32; i++) if(vi[i] >= 0) for(j = 0; j < 32; j++) if(vi[j] >= 0) c[vi[i]][vi[j]] = F[i ^ j];ksm(n / K, 10);for(i = 0; i < 10; i++) d[i] = f[X][i];Ksm(n % K, 32);for(i = 0; i < 10; i++) for(j = 0; j < 10; j++) ans[j] = (ans[j] + d[i] * F[p[i] ^ p[j]]) % md;for(i = 0; i < 10; i++) printf("%lld\n", ans[i]);}else {for(i = 0; i < 10; i++) C[1 << i] = 1;Ksm(K, 1024);memset(vi, 255, sizeof(vi));for(i = 0; i < 10; i++) for(j = 0; j < 10; j++) vi[p[i] * 32 + p[j]] = i * 10 + j;for(i = 0; i < 1024; i++) if(vi[i] >= 0) for(j = 0; j < 1024; j++) if(vi[j] >= 0) c[vi[i]][vi[j]] = F[i ^ j];ksm(n / K, 100);for(i = 0; i < 100; i++) d[i] = f[X][i];Ksm(n % K, 1024);for(i = 0; i < 100; i++) for(j = 0; j < 100; j++) ans[j] = (ans[j] + d[i] * F[(p[i / 10] * 32 + p[i % 10]) ^ (p[j / 10] * 32 + p[j % 10])]) % md;for(i = 0; i < 100; i++) printf("%lld\n", ans[i]);} return 0;
}

COI 2020 Semafor(矩阵乘法+优化)相关推荐

  1. 形态形成场(矩阵乘法优化dp)

    形态形成场(矩阵乘法优化dp) 短信中将会涉及前\(k\)种大写字母,每个大写字母都有一个对应的替换式\(Si\),替换式中只会出现大写字母和数字,比如\(A→BB,B→CC0,C→123\),代表 ...

  2. 【BZOJ 3326】[Scoi2013]数数 数位dp+矩阵乘法优化

    挺好的数位dp-- 先说一下我个人的做法: 经过观察,发现这题按照以往的思路从后往前递增,不怎么好推,然后我就大胆猜想,从前往后推,发现很好推啊,维护四个变量,从开始位置到现在有了i个数 f[i]:所 ...

  3. CUDA实例系列一: 矩阵乘法优化

    CUDA实例系列一----矩阵乘法优化 很多朋友在学习CUDA的时候都会面临一个题目----矩阵乘法, 这也是CUDA最广泛的应用之一. 本文将详细讲解如何利用GPU加速矩阵乘法的计算. 话不多说, ...

  4. OpenBLAS项目与矩阵乘法优化 | AI 研习社

    提起矩阵计算,学过<高等数学>的人可能都听过,但若不是这个领域的研究者,恐怕也只停在"听过"的程度.在矩阵计算领域,开源项目OpenBLAS影响巨大,除IBM.华为等巨 ...

  5. 【Contra】 矩阵乘法优化 dp

    偶然间,chnlich发现了他小时候玩过的一个游戏"魂斗罗",于是决定怀旧.但是这是一个奇怪的魂斗罗MOD.有N个关卡,初始有Q条命.每通过一个关卡,会得到u分和1条命,生命上限为 ...

  6. 并行程序设计方法实验(包括openmp、向量化实现pi计算、SPECOMP2012测试、矩阵乘法优化)

    目录 一.实验环境 二.专题一之积分计算圆周率 2.1向量优化 2.2 OpenMP优化 三.专题二之测试SPECOMP2012 3.1初步了解SPECOMP 3.2系统基本配置 3.3实践 3.3. ...

  7. 基于how-to-optimize-gemm初探矩阵乘法优化

    1. 前言 这次,我们来聊一个轻松一点的话题,那就是给你一个矩阵A和一个矩阵B,使用矩阵乘法获得目标矩阵C,相信大家都不难写出下面的代码: #define A( i, j ) a[ (i)*lda + ...

  8. 矩阵乘法 递归 优化 c语言,矩阵乘法优化递归式

    序: 在OI比赛中,很多情况下我们可以能通过打表(找规律)或者某些方式发现一个递归式. 例如:f(n) = f(n - 1)+f(n - 2),(斐波那契数列). 通常情况下,我们计算f(n)的时间复 ...

  9. CUDA 矩阵乘法优化

    这个完全是基础知识啊~~  哪不对 大佬们帮忙指出啊 CUDA 矩阵乘法优化手段详解 Naive 实现的分析:到底差在哪里? 笔者面试过不少具有 CUDA 编程经验的校招同学,当提问使用 CUDA 编 ...

最新文章

  1. 【408预推免复习】计算机组成原理之计算机的发展及应用
  2. 创建表名作为参数的mysq存储过程【procedure】
  3. React应用里Invalid hook call错误消息的处理
  4. 如何将函数的实际参数转换成数组
  5. Tensorflow 相关概念
  6. HashTable Dictionary HashMap
  7. FFmpeg编解码器如何
  8. oracle 卸载(手动,无universal installer)
  9. 关于帧差法的想法(opencv)
  10. Ubuntu系统通用快捷键
  11. 联想K31笔记本完全拆解,装不回去了。想做个电视机或者显示器
  12. 计算机主机电源品牌有哪些,电脑电源的一线品牌有哪些?
  13. 肠道细菌四大“门派”——拟杆菌门,厚壁菌门,变形菌门,放线菌门
  14. JAVA期末考广东科技学院,我是叩丁狼广州Java老学员,我来说说自己的故事
  15. 安装eclipse c++版本neno
  16. js文字转图片,使用画布绘制
  17. vue提示Named Route ‘News‘ has a default child route. When navigating to this named route...问题
  18. 计算机无法共享的原因,不能共享的原因
  19. 嵌入式Linux驱动笔记(五)------学习platform设备驱动
  20. B. Sheldon and Ice Pieces

热门文章

  1. 边沿检测电路的多种实现
  2. 软件测试初学者,手把手教你如何编写一份高效好用的测试用例
  3. C语言自动识别文本编码
  4. 设计一个中国象棋游戏,ChessPiece为抽象类,提供代表一个棋子位置的属性和方法,和isMoveLegal();设计ChessPiece的具体实现类(如车,马,帅等)
  5. 鸿蒙系统电视k歌,前沿讯息:华为电视K歌模式 开启当贝音乐 曲库任意选 功能很强大...
  6. 构建推荐系统:用 Netflix 电影评价数据集练练手
  7. servers split sql_SQL中实现SPLIT函数几种方法总结(必看篇)
  8. 【问题处理】Error response from daemon: Pool overlaps with other one on this address space
  9. unity学习——遮挡剔除
  10. 华为发布BB智能观影产品:Vision Glass