COI 2020 Semafor(矩阵乘法+优化)
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 次合法的数之间的转移,最后再算上剩下NmodKN\operatorname{mod}KNmodK 次操作。
- 计算一下复杂度,合法的数之间的转移最大是1023∗logN=106∗logN{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=xxoryk=x\operatorname{xor}yk=xxory。那么对固定的kkk,任意xxx转移到xxorkx\operatorname{xor} kxxork的方案数都相等,所以转移矩阵就不需要维护210∗2102^{10}*2^{10}210∗210大小,而只需记录不同的转移kkk的值。
- 转移时直接枚举iii和jjj转移到ixorji\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(矩阵乘法+优化)相关推荐
- 形态形成场(矩阵乘法优化dp)
形态形成场(矩阵乘法优化dp) 短信中将会涉及前\(k\)种大写字母,每个大写字母都有一个对应的替换式\(Si\),替换式中只会出现大写字母和数字,比如\(A→BB,B→CC0,C→123\),代表 ...
- 【BZOJ 3326】[Scoi2013]数数 数位dp+矩阵乘法优化
挺好的数位dp-- 先说一下我个人的做法: 经过观察,发现这题按照以往的思路从后往前递增,不怎么好推,然后我就大胆猜想,从前往后推,发现很好推啊,维护四个变量,从开始位置到现在有了i个数 f[i]:所 ...
- CUDA实例系列一: 矩阵乘法优化
CUDA实例系列一----矩阵乘法优化 很多朋友在学习CUDA的时候都会面临一个题目----矩阵乘法, 这也是CUDA最广泛的应用之一. 本文将详细讲解如何利用GPU加速矩阵乘法的计算. 话不多说, ...
- OpenBLAS项目与矩阵乘法优化 | AI 研习社
提起矩阵计算,学过<高等数学>的人可能都听过,但若不是这个领域的研究者,恐怕也只停在"听过"的程度.在矩阵计算领域,开源项目OpenBLAS影响巨大,除IBM.华为等巨 ...
- 【Contra】 矩阵乘法优化 dp
偶然间,chnlich发现了他小时候玩过的一个游戏"魂斗罗",于是决定怀旧.但是这是一个奇怪的魂斗罗MOD.有N个关卡,初始有Q条命.每通过一个关卡,会得到u分和1条命,生命上限为 ...
- 并行程序设计方法实验(包括openmp、向量化实现pi计算、SPECOMP2012测试、矩阵乘法优化)
目录 一.实验环境 二.专题一之积分计算圆周率 2.1向量优化 2.2 OpenMP优化 三.专题二之测试SPECOMP2012 3.1初步了解SPECOMP 3.2系统基本配置 3.3实践 3.3. ...
- 基于how-to-optimize-gemm初探矩阵乘法优化
1. 前言 这次,我们来聊一个轻松一点的话题,那就是给你一个矩阵A和一个矩阵B,使用矩阵乘法获得目标矩阵C,相信大家都不难写出下面的代码: #define A( i, j ) a[ (i)*lda + ...
- 矩阵乘法 递归 优化 c语言,矩阵乘法优化递归式
序: 在OI比赛中,很多情况下我们可以能通过打表(找规律)或者某些方式发现一个递归式. 例如:f(n) = f(n - 1)+f(n - 2),(斐波那契数列). 通常情况下,我们计算f(n)的时间复 ...
- CUDA 矩阵乘法优化
这个完全是基础知识啊~~ 哪不对 大佬们帮忙指出啊 CUDA 矩阵乘法优化手段详解 Naive 实现的分析:到底差在哪里? 笔者面试过不少具有 CUDA 编程经验的校招同学,当提问使用 CUDA 编 ...
最新文章
- 【408预推免复习】计算机组成原理之计算机的发展及应用
- 创建表名作为参数的mysq存储过程【procedure】
- React应用里Invalid hook call错误消息的处理
- 如何将函数的实际参数转换成数组
- Tensorflow 相关概念
- HashTable Dictionary HashMap
- FFmpeg编解码器如何
- oracle 卸载(手动,无universal installer)
- 关于帧差法的想法(opencv)
- Ubuntu系统通用快捷键
- 联想K31笔记本完全拆解,装不回去了。想做个电视机或者显示器
- 计算机主机电源品牌有哪些,电脑电源的一线品牌有哪些?
- 肠道细菌四大“门派”——拟杆菌门,厚壁菌门,变形菌门,放线菌门
- JAVA期末考广东科技学院,我是叩丁狼广州Java老学员,我来说说自己的故事
- 安装eclipse c++版本neno
- js文字转图片,使用画布绘制
- vue提示Named Route ‘News‘ has a default child route. When navigating to this named route...问题
- 计算机无法共享的原因,不能共享的原因
- 嵌入式Linux驱动笔记(五)------学习platform设备驱动
- B. Sheldon and Ice Pieces
热门文章
- 边沿检测电路的多种实现
- 软件测试初学者,手把手教你如何编写一份高效好用的测试用例
- C语言自动识别文本编码
- 设计一个中国象棋游戏,ChessPiece为抽象类,提供代表一个棋子位置的属性和方法,和isMoveLegal();设计ChessPiece的具体实现类(如车,马,帅等)
- 鸿蒙系统电视k歌,前沿讯息:华为电视K歌模式 开启当贝音乐 曲库任意选 功能很强大...
- 构建推荐系统:用 Netflix 电影评价数据集练练手
- servers split sql_SQL中实现SPLIT函数几种方法总结(必看篇)
- 【问题处理】Error response from daemon: Pool overlaps with other one on this address space
- unity学习——遮挡剔除
- 华为发布BB智能观影产品:Vision Glass