蒟蒻的我还需深入学习

**链接:****传送门 **

题意:给出一个长度为 n,n 不超过100的 01 串 s ,每当一个数字左侧为 1 时( 0的左侧是 n-1 ),这个数字就会发生改变,整个串改变一次需要 1s ,询问 M s 后此串变为什么样子,例如 0101111 ,1s 后变为 1111000

思路:

  • 根据题意可以得到这样一个规律 s[ i ] = ( s[ i - 1 ] + s[ i ] ) % 2,特别的 s[ 0 ] = ( s[ n-1 ] + s[ 0 ] ) % 2 ( s[ ] 不再考虑为char ),构造矩阵a、b、ans

    • 假设 01 串长为 5,下图为矩阵a
    1 0 0 0 1
    1 1 0 0 0
    0 1 1 0 0
    0 0 1 1 0
    0 0 0 1 1
    • 矩阵b
    s0 0 0 0 0
    s1 0 0 0 0
    s2 0 0 0 0
    s3 0 0 0 0
    s4 0 0 0 0
    • 矩阵 ans
    s0 0 0 0 0
    s1 0 0 0 0
    s2 0 0 0 0
    s3 0 0 0 0
    s4 0 0 0 0
    • 矩阵 ans = a * b,假设经过 Ms 后矩阵 ans = pow( a, M ) * b,此时的 b 中的 s[ ] 为起始的 01 串,所以通过矩阵快速幂就可以解决了
  • 解决此题的三种姿势

    • 1.普通矩阵快速幂,经过上面分析很容易写出该方法对应的程序

    • 2.循环同构矩阵优化矩阵快速幂,经上面分析可以看出矩阵 a 为典型的循环同构矩阵,( 什么是循环矩阵?**戳这里! ** )对于循环同构矩阵可以先算出来第 0 行然后递推下面的剩余行,从而将计算 pow( a , n ) 的复杂度 O( n ^ 3 ) 降为 O( n ^ 2 ),需要注意的时,这种方法应该只能用来优化同构矩阵的计算,如果是一个同构矩阵 × 其他矩阵,递推剩下行数是错误的!这道题不会卡复杂度......

    • 3.循环同构矩阵优化矩阵快速幂 + 位运算,可以把矩阵乘法中的 * 换成 & , % 2 换成 ^(XOR)


姿势1:

/*************************************************************************
> File Name: hdu2276.cpp
> Author: WArobot
> Blog: http://www.cnblogs.com/WArobot/
> Created Time: 2017年05月04日 星期四 14时32分45秒
************************************************************************/ #include<bits/stdc++.h>
using namespace std; int n,len;
string s;
const int MOD = 2;
const int maxn = 110;
#define ll long long
#define mod(x) ((x)%MOD)
#define cls(x) memset(x,0,sizeof(x)); struct mat{
int m[maxn][maxn];
}unit; void init_unit(){
for(int i=0;i<maxn;i++) unit.m[i][i] = 1;
}
mat operator *(mat a,mat b){
mat ret;
ll x;
for(int i=0;i<len;i++){
for(int j=0;j<len;j++){
x = 0;
for(int k=0;k<len;k++)
x += mod( a.m[i][k]*b.m[k][j] );
ret.m[i][j] = mod(x);
}
}
return ret;
}
mat pow_mat(mat a,int x){
mat ret = unit;
while(x){
if(x&1) ret = ret*a;
a = a*a;
x >>= 1;
}
return ret;
} mat a,b;
void init(){
cls(a.m);
a.m[0][0] = a.m[0][len-1] = 1;
for(int i=1;i<len;i++) a.m[i][i-1] = a.m[i][i] = 1;
}
int main(){
init_unit();
while(cin >> n >> s){
len = s.size();
init(); mat ans = pow_mat(a,n);
cls(b.m);
for(int i=0;i<len;i++)
b.m[i][0] = s[i]-'0';
ans = ans*b;
for(int i=0;i<len;i++) printf("%d",ans.m[i][0]);
printf("\n");
}
return 0;
}

姿势2:

/*************************************************************************
> File Name: hdu2276t2.cpp
> Author: WArobot
> Blog: http://www.cnblogs.com/WArobot/
> Created Time: 2017年05月04日 星期四 14时57分05秒
************************************************************************/ #include<bits/stdc++.h>
using namespace std; int n,len;
string s;
const int MOD = 2;
const int maxn = 110;
#define ll long long
#define mod(x) ((x)%MOD)
#define cls(x) memset(x,0,sizeof(x)); struct mat{
int m[maxn][maxn];
}unit; void init_unit(){
for(int i=0;i<maxn;i++) unit.m[i][i] = 1;
}
// 根据循环矩阵可以优化矩阵乘法
// 因为循环矩阵a[i][i] = a[i-1][i-1] , 所以只需要计算出第0行然后递推剩下的其他行就ok了
mat operator *(mat a,mat b){
mat ret;
cls(ret.m);
for(int i=0;i<len;i++)
for(int j=0;j<len;j++)
ret.m[0][i] = mod( ret.m[0][i] + mod(a.m[0][j]&b.m[j][i]) );
for(int i=1;i<len;i++)
for(int j=0;j<len;j++)
ret.m[i][j] = ret.m[i-1][ (j-1+len)%len ];
return ret;
}
mat pow_mat(mat a,int x){
mat ret = unit;
while(x){
if(x&1) ret = ret*a;
a = a*a;
x >>= 1;
}
return ret;
} mat a,b;
void init(){
cls(a.m);
a.m[0][0] = a.m[0][len-1] = 1;
for(int i=1;i<len;i++) a.m[i][i-1] = a.m[i][i] = 1;
}
int main(){
init_unit();
while(cin >> n >> s){
len = s.size();
init(); // 使用循环矩阵只能计算矩阵a^n,因为只有矩阵a有循环矩阵的特点
mat ans = pow_mat(a,n); for(int i=0;i<len;i++){
ll tmp = 0;
for(int j=0;j<len;j++){
tmp = mod( tmp + mod(ans.m[i][j]*(s[j]-'0')) );
}
cout<<tmp;
}
cout<<endl;
}
return 0;
}

姿势3:

/*************************************************************************
> File Name: hdu2276t3.cpp
> Author: WArobot
> Blog: http://www.cnblogs.com/WArobot/
> Created Time: 2017年05月04日 星期四 15时41分45秒
************************************************************************/ #include<bits/stdc++.h>
using namespace std; int n,len;
string s;
const int MOD = 2;
const int maxn = 110;
#define ll long long
#define mod(x) ((x)%MOD)
#define cls(x) memset(x,0,sizeof(x)); struct mat{
int m[maxn][maxn];
}unit; void init_unit(){
for(int i=0;i<maxn;i++) unit.m[i][i] = 1;
}
// 根据循环矩阵可以优化矩阵乘法
// 因为循环矩阵a[i][i] = a[i-1][i-1] , 所以只需要计算出第0行然后递推剩下的其他行就ok了
mat operator *(mat a,mat b){
mat ret;
cls(ret.m);
for(int i=0;i<len;i++)
for(int j=0;j<len;j++)
ret.m[0][i] ^= (a.m[0][j] & b.m[j][i]);
for(int i=1;i<len;i++)
for(int j=0;j<len;j++)
ret.m[i][j] = ret.m[i-1][ (j-1+len)%len ];
return ret;
}
mat pow_mat(mat a,int x){
mat ret = unit;
while(x){
if(x&1) ret = ret*a;
a = a*a;
x >>= 1;
}
return ret;
} mat a,b;
void init(){
cls(a.m);
a.m[0][0] = a.m[0][len-1] = 1;
for(int i=1;i<len;i++) a.m[i][i-1] = a.m[i][i] = 1;
}
int main(){
init_unit();
while(cin >> n >> s){
len = s.size();
init(); // 使用循环矩阵只能计算矩阵a^n,因为只有矩阵a有循环矩阵的特点
mat ans = pow_mat(a,n); for(int i=0;i<len;i++){
ll tmp = 0;
for(int j=0;j<len;j++)
tmp ^= (ans.m[i][j] & (s[j]-'0'));
printf("%lld",tmp);
}
printf("\n");
}
return 0;
}

HDU 2276 Kiki & Little Kiki 2( 矩阵快速幂 + 循环同构矩阵 )的更多相关文章

  1. HDU1757-A Simple Math Problem,矩阵快速幂,构造矩阵水过

    A Simple Math Problem 一个矩阵快速幂水题,关键在于如何构造矩阵.做过一些很裸的矩阵快速幂,比如斐波那契的变形,这个题就类似那种构造.比赛的时候手残把矩阵相乘的一个j写成了i,调试 ...

  2. HDU6395-Sequence 矩阵快速幂+除法分块 矩阵快速幂模板

    目录 Catalog Solution: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 Catalog Problem:Portal传送门  原题目描述在最下面. Solution ...

  3. HDU_4965 Fast Matrix Calculation 2014多校9 矩阵快速幂+机智的矩阵结合律

    一开始看这个题目以为是个裸的矩阵快速幂的题目, 后来发现会超时,超就超在  M = C^(N*N). 这个操作,而C本身是个N*N的矩阵,N最大为1000. 但是这里有个巧妙的地方就是 C的来源其实 ...

  4. LA 3704 (矩阵快速幂 循环矩阵) Cellular Automaton

    将这n个格子看做一个向量,每次操作都是一次线性组合,即vn+1 = Avn,所求答案为Akv0 A是一个n*n的矩阵,比如当n=5,d=1的时候: 不难发现,A是个循环矩阵,也就是将某一行所有元素统一 ...

  5. 经典矩阵快速幂之一-----poj3233(矩阵套矩阵

    题意:给你一个矩阵A,求S=A+A^2+A^3+...+A^k. 其实这个当时我看着毫无头绪,看了他们给的矩阵发现好!精!妙! 我们这样看 是不是有点思路! 没错!就是右上角,我们以此类推可以得到A+ ...

  6. hdu 2604 Queuing(矩阵快速幂乘法)

    Problem Description Queues and Priority Queues are data structures which are known to most computer ...

  7. (hdu 6030) Happy Necklace 找规律+矩阵快速幂

    题目链接 :http://acm.hdu.edu.cn/showproblem.php?pid=6030 Problem Description Little Q wants to buy a nec ...

  8. HDU 6470 【矩阵快速幂】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6470 写这道题是为了让自己不要忘记矩阵快速幂如何推出矩阵式子的. 注意 代码是TLE的!! #incl ...

  9. HDU 5318——The Goddess Of The Moon——————【矩阵快速幂】

    The Goddess Of The Moon Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/ ...

随机推荐

  1. mysql修改时区的几种方法(转载自https://www.cnblogs.com/shiqiangqiang/p/8393662.html)

    说明: 以下记录修改mysql时区的几种方法. 具体: 方法一:通过mysql命令行模式下动态修改 1.1 查看mysql当前时间,当前时区 select curtime(); #或select no ...

  2. 【 ACM-ICPC 2018 沈阳赛区网络预赛 D】Made In Heaven

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 点可以重复走的k短路. [代码] #include <bits/stdc++.h> #define LL long lo ...

  3. JS中的call()(转)

    1.方法定义 call方法: 语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象. 说明: call 方 ...

  4. BA-siemens-apogee总线不稳定解决方法

    状况一:BLN下的火车头在线,但是下面的模块(包括UEC或者PPM)全部掉线 尝试方法: 使用挨个DDC箱断线的方法测试总线是否上线(可以解决由于总线短路引起的总线故障,施工中总线压冷压端子的话就不容 ...

  5. BA--调试经验笔记

    100%的湿度是水蒸气,称做饱和空气,人体的相对湿度范围为20%---60%,当室内的湿度小于20%时,容易产生静电,尤其在计算机上,超过60%就过湿 冬天适宜温度24.5+-1.5,夏天适宜温度22 ...

  6. HDU 2838 (树状数组求逆序数)

    题意: 给你N个排列不规则的数(1~N),任务是把它从小到大排好,每次仅仅能交换相邻两个数,交换一次的代价为两数之和.求最小代价 思路:对于当前数X.我们如果知道前面比它大的数有多少,如果为K,那么有 ...

  7. 命令模式之2 Invoker Vs. Client

    当程序中直接编写下达命令的语句如new Cmd1().execute()时.一般会将调用者与客户类合二为一. 在GUI程序中.下达命令的语句通常包括在底层框架中.或者说底层框架包括了调用者.这时程序猿 ...

  8. Android学习之——优化篇(1)

    一.优化的品质 1.简练.2.可读性强.3.模块化:4.层次性:5.设计良好.6.高效.7.优雅:8.清晰. 二.常见的编程规范     1. 基本要求 · 结构清晰,简单易懂.单个函数不超过100行 ...

  9. 2015.05.12,外语,读书笔记-《Word Power Made Easy》 15 “如何谈论不同人的特点” SESSION 45

    TEASER PREVIEW 以-ous结尾的,描绘某人特点的词语包括: fawning(['fɔ:niŋ] adj.奉承的),servilely(['sә:vail] adj. 卑屈的, 奴隶的) ...

  10. Hello The World! —— 致我们无悔的IT之旅

    感谢IT,让我有了这么可爱活泼的伙伴. 有了KsCla,Coming,lhx_QAQ,tututu,AB_ever,Fat-zhang,wka,lhm这些伙伴神犇的陪伴,我的OI历程不至于那么枯燥无味 ...