UOJ 241. 【UR #16】破坏发射台

题意:长度为 n 的环,每个点染色,有 m 种颜色,要求相邻相对不能同色,求方案数。(定义两个点相对为去掉这两个点后环能被分成相同大小的两段)


只想到一个奇怪的线性递推,无法写成矩乘的形式...


正解用状态记录了颜色是否相同

奇环,只考虑相邻,确定第一个的颜色,\(f[i][0/1]\)表示i个与第一个不同/同色的方案数

偶环,再考虑相对,分成两段,同时递推\(i,\frac{n}{2}+i\),\(f[i][0..6]\)来表示

构造矩阵讨论好烦啊

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int mo = 998244353;
inline int read() {
char c=getchar(); int x=0,f=1;
while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return x*f;
} int n, m, r, g[7][7], f[7][7];
void mul(int a[7][7], int b[7][7]) {
static int c[7][7];
memset(c, 0, sizeof(c));
for(int i=0; i<r; i++)
for(int k=0; k<r; k++) if(a[i][k])
for(int j=0; j<r; j++) if(b[k][j])
c[i][j] = (c[i][j] + (ll) a[i][k] * b[k][j]) %mo;
memcpy(a, c, sizeof(c));
}
void Pow(int a[7][7], int b) {
static int c[7][7];
memset(c, 0, sizeof(c));
for(int i=0; i<r; i++) c[i][i] = 1;
for(; b; b >>= 1, mul(a, a)) if(b & 1) mul(c, a);
memcpy(a, c, sizeof(c));
}
void print(int a[7][7]) {
for(int i=0; i<r; i++) for(int j=0; j<r; j++) printf("%d%c", a[i][j], j==r-1 ? '\n' : ' ');
puts("");
}
namespace odd {
void solve() {
r = 2;
g[0][0] = m-2; g[0][1] = m-1;
g[1][0] = 1; g[1][1] = 0;
Pow(g, n-2);
//print(g);
f[0][0] = m-1; f[1][0] = 0;
mul(g, f);
//print(g);
int ans = (ll) g[0][0] * m %mo;
printf("%d\n", ans);
}
}
namespace even {
int id[5][5];
inline ll cal(int a, int c) {
if(a == 0) return c==0 ? m-3 : m-2;
else return 1;
}
void solve() {
r = 7;
memset(id, -1, sizeof(id));
id[0][0] = 0; id[0][1] = 1; id[0][2] = 2;
id[1][0] = 3; id[1][2] = 4;
id[2][0] = 5; id[2][1] = 6;
for(int a=0; a<3; a++) for(int b=0; b<3; b++) if(~id[a][b])
for(int c=0; c<3; c++) for(int d=0; d<3; d++) if(~id[c][d]) {
int i = id[a][b], j = id[c][d];
if((a && a==c) || (b && b==d)) continue;
if(a == 0 && b == 0) { //printf("hi\n");
if(c && d) g[i][j] = (ll) (m-2) * max(0, m-3) %mo;
else if(!c && !d) g[i][j] = ((ll) max(0, m-4) * max(0, m-4) + max(0, m-3)) %mo;
else if(c || d) g[i][j] = ((ll) max(0, m-3) * max(0, m-3)) %mo;
g[i][j] = max(0, g[i][j]);
} else g[i][j] = cal(a, c) * cal(b, d) %mo;
}
//print(g);
f[id[0][0]][0] = max(0LL, (ll)(m-2) * (m-3)) %mo;
f[id[0][1]][0] = m-2;
f[id[2][0]][0] = m-2;
f[id[2][1]][0] = 1;
n = n/2 - 1;
Pow(g, n-1);
//print(g);
mul(g, f);
//print(g);
int ans = (ll) ((ll) g[0][0] + g[id[1][0]][0] + g[id[0][2]][0] + g[id[1][2]][0]) %mo * m %mo * (m-1) %mo;
printf("%d\n", ans);
}
}
int main() {
freopen("in", "r", stdin);
n = read(); m = read();
if(n == 1) printf("%d\n", m);
else if(n == 2) printf("%lld\n", (ll) m * (m-1) %mo);
if(n & 1) odd::solve();
else even::solve();
}

UOJ 241. 【UR #16】破坏发射台 [矩阵乘法]的更多相关文章

  1. [UOJ UR#16]破坏发射台

    来自FallDream的博客,未经允许,请勿转载,谢谢. 传送门 先考虑n是奇数的情况,很容易想到一个dp,f[i][0/1]表示转移到第i个数,第i个数是不是第一个数的方案数,然后用矩阵乘法优化一下 ...

  2. 【UOJ#242】【UR#16】破坏蛋糕(计算几何)

    [UOJ#242][UR#16]破坏蛋糕(计算几何) 题面 UOJ 题解 为了方便,我们假定最后一条直线是从上往下穿过来的,比如说把它当成坐标系的\(y\)轴. 于是我们可以处理出所有交点,然后把它们 ...

  3. 矩阵乘法的MapReduce实现

    对于任意矩阵M和N,若矩阵M的列数等于矩阵N的行数,则记M和N的乘积为P=M*N,其中mik 记做矩阵M的第i行和第k列,nkj记做矩阵N的第k行和第j列,则矩阵P中,第i行第j列的元素可表示为公式( ...

  4. 第四章 分治策略 4.2 矩阵乘法的Strassen算法

    package chap04_Divide_And_Conquer; import static org.junit.Assert.*; import java.util.Arrays; import ...

  5. 【模拟题(电子科大MaxKU)】解题报告【树形问题】【矩阵乘法】【快速幂】【数论】

    目录: 1:一道简单题[树形问题](Bzoj 1827 奶牛大集会) 2:一道更简单题[矩阵乘法][快速幂] 3:最简单题[技巧] 话说这些题目的名字也是够了.... 题目: 1.一道简单题 时间1s ...

  6. 基于OpenMP的矩阵乘法实现及效率提升分析

    一.  矩阵乘法串行实现 例子选择两个1024*1024的矩阵相乘,根据矩阵乘法运算得到运算结果.其中,两个矩阵中的数为double类型,初值由随机数函数产生.代码如下: #include <i ...

  7. Codevs No.1287 矩阵乘法

    2016-06-01 16:53:23 题目链接: 矩阵乘法 (Codevs No.1287) 题目大意: 给你两个可乘矩阵a,b,求a*b 解法: 定义....... //矩阵乘法 (Codevs ...

  8. 2.3CUDA矩阵乘法

    CPU 矩阵乘法 能相乘的两个矩阵,必须满足一个矩阵的行数和第二个矩阵的列数相同. A(N*P) * B(P*M) = C(N*M). 其中P是行数,N是列数, 从宽高的角度来说,即 A的宽度和B的高 ...

  9. 【POJ2778】AC自动机+矩阵乘法

    DNA Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14758 Accepted: 5716 Descrip ...

随机推荐

  1. 51 Nod 1119

    机器人走方格 V2 M * N的方格,一个机器人从左上走到右下,只能向右或向下走.有多少种不同的走法?由于方法数量可能很大,只需要输出Mod 10^9 + 7的结果. Input 第1行,2个数M,N ...

  2. 2017ecjtu-summer training # 11 POJ 2492

    A Bug's Life Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 38280   Accepted: 12452 D ...

  3. linux(CENTOS)系统各个目录的作用详解

    Linux(CentOS)系统各个目录的作用详解 文件的类型 LINUX有四种基本文件系统类型:普通文件.目录文件.连接文件和特殊文件,可用file命令来识别. 普通文件:如文本文件.C语言元代码.S ...

  4. [Golang]一道考察defer与命名返回值的题目

    题目 输出: 4 1 3 解释 当函数有可命名结果形参时,结果形参的初始值被设置为零值,函数的return语句会设置结果形参的值 当函数有可命名结果形参时,defer函数是可以修改它,然后再将它的值返 ...

  5. 部署Asp.net Core 项目发生502.5 或者500 没有其他提示信息

    最近将公司原来.NetCore 1.6的项目升级到.net Core 2.0首先发生 502.5的错误,包括IIS日志,Windows应用程序日志都没有记录问题始终解决不了,首先看看官网给出的解决方案 ...

  6. ProtoBuf 与 gRPC

    用 Protobuf 很久了,但是一直觉得很简单,所以就没有做一个总结,今天想尝试一下 gRPC,顺带就一起总结一下.ProtoBuf 是个老同志了,应该是 2010 的时候发布的,然后被广泛使用,目 ...

  7. vi命令加行号查找替换等命令

    一.加行号           : set nu二.vi查找:    当你用vi打开一个文件后,因为文件太长,如何才能找到你所要查找的关键字呢?在vi里可没有菜单-〉查找,              ...

  8. Java进阶篇(三)——Java集合类

    集合可以看作一个容器,集合中的对象可以很容易存放到集合中,也很容易将其从集合中取出来,还可以按一定的顺序摆放.Java中提供了不同的集合类,这些类具有不同的存储对象的方式,并提供了相应的方法方便用户对 ...

  9. mybatis_SQL缓存(5)

    <settings> <!-- 这个配置使全局的映射器启用或禁用缓存 --> <setting name="cacheEnabled" value=& ...

  10. git log 查看指定文件的提交记录

    使用git log除了可以看整个仓库的提交记录外,还可以指定某个文件的提交记录. 1. 查看指定文件的历史提交记录 命令: git log -- <file> 说明:只需要指定文件名称. ...