ACdream 1093 女神的正多面体 矩阵快速幂

题目大意:给你三种正多边形,给你起点s,终点e以及最多行走的步数k,问有多少种路径方案(路径中只要有一个顶点不同即视为不同)。

题目分析:

可以通过矩阵快速幂求解。

为每个正多边形(最多三个)构建一个邻接矩阵A,然后第K步的方案数即为A^k。

结果即为A^1 + A^2 + A^3 + ...... + A^k.

对于这种形式的矩阵运算,我们可以把它拆分成:

k为奇:ans = (A^1 + A^2 + ... + A^(k/2)) + (A^1 + A^2 + ... + A^(k/2)) * A^(k.2)
+ A^k;

k为偶:ans = (A^1 + A^2 + ... + A^(k/2)) + (A^1 + A^2 + ... + A^(k/2)) *
A^(k.2);

合并一下就是:

ans = (A^1 + A^2 + ... + A^(k/2)) * (A(k/2) + 1);

if(k & 1) ans = ans + A^k;

结果即为mat[s - 1][e - 1](保存的时候下标均以减一)。

PS:本蒟蒻的代码效率貌似一直不高的样子QUQ。。。路过的众神们见谅QUQ。。。

代码如下:

#include <stdio.h>
#include <string.h>
#define REP(i, n) for(int i = 0; i < n; ++i)
typedef long long ll;
const int mod = 1000000007;
const int O = 8;
int N, K;
typedef struct M{
ll mat[O][O];
M operator * (const M &t) const{//重载矩阵乘法
M tmp;
memset(tmp.mat, 0, sizeof(tmp.mat));
REP(i, N) REP(j, N) REP(k, N) tmp.mat[i][j] = (tmp.mat[i][j] + mat[i][k] * t.mat[k][j]) % mod;
return tmp;
}

//不使用函数的原因是为了让快速幂看起来更加自然

M operator + (const M &t) const{//重载矩阵加法
M tmp;
REP(i, N) REP(j, N) tmp.mat[i][j] = (mat[i][j] + t.mat[i][j]) % mod;
return tmp;
}
}M;
M A[3] = {
{{//正四边形
{0, 1, 1, 1},
{1, 0, 1, 1},
{1, 1, 0, 1},
{1, 1, 1, 0},
}},
{{//正六边形
{0, 1, 0, 1, 1, 0, 0, 0},
{1, 0, 1, 0, 0, 1, 0, 0},
{0, 1, 0, 1, 0 ,0, 1, 0},
{1, 0, 1, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 1, 0, 1},
{0, 1, 0, 0, 1, 0, 1, 0},
{0, 0, 1, 0, 0 ,1, 0, 1},
{0, 0, 0, 1, 1, 0, 1, 0},
}},
{{//正八边形
{0, 1, 1, 1, 1, 0},
{1, 0, 1, 0, 1, 1},
{1, 1, 0, 1, 0, 1},
{1, 0, 1, 0, 1, 1},
{1, 1, 0, 1, 0, 1},
{0, 1, 1, 1, 1, 0},
}},
}, E;
M pow(ll k){//矩阵快速幂求A^k.
M res = E, tmp = A[K];
for(; k; k >>= 1){
if(k & 1) res = res * tmp;
tmp = tmp * tmp;
}
return res;
}
M _pow(ll k){//递归快速幂求A^1 + A^2 + A^3 + ...... + A^k.
if(k == 1) return A[K];
M res = _pow(k >> 1) * (E + pow(k >> 1));
if(k & 1) res = res + pow(k);
return res;
}
void work(){
int t, n, s, e;
ll k;
REP(i, O) REP(j, O) E.mat[i][j] = (i == j);//初始化单位矩阵
scanf("%d", &t);
while(t--){
scanf("%d%lld%d%d", &n, &k, &s, &e);
N = (n == 4 ? 4 : (n == 6 ? 8 : 6));//选择矩阵需要的范围
K = (n == 4 ? 0 : (n == 6 ? 1 : 2));//选择正多边形的类型
printf("%lld\n", _pow(k).mat[s - 1][e - 1]);
}
}
int main(){
work();
return 0;
}

1093

支持原创,转载还请注明出处:http://www.cnblogs.com/ac-luna/        ——Luna

时间: 2024-10-28 14:42:55

ACdream 1093 女神的正多面体 矩阵快速幂的相关文章

acdream 1093 女神的正多面体

http://acdream.info/problem?pid=1093 女神的正多面体 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 128000/64000 KB (Java/Others) SubmitStatistic Next Problem Problem Description EOF女神灰常喜欢整齐的东西,例如多面体中最喜欢的就是正多面体.正多面体的定义为:指每个面都是全等的正多边形的多面体.欧拉大人告诉我们,正多面体只

[BZOJ3583]杰杰的女性朋友(矩阵快速幂)

杰杰的女性朋友 时间限制:10s      空间限制:256MB 题目描述 杰杰是魔法界的一名传奇人物.他对魔法具有深刻的洞察力,惊人的领悟力,以及令人叹为观止的创造力.自从他从事魔法竞赛以来,短短几年时间,就已经成为 世界公认的实力最强的魔法选手之一.更让人惊叹的是,他几乎没有借助外界力量,完全凭借自己的努力达到了普通人难以企及的高度.在最近的世界魔法奥林匹克 竞赛上,他使用高超的魔法本领,一路过关斩将,在最后时刻一举击败了前冠军"旅行者",获得了魔法界最高的荣耀:女神奖杯!女神奖杯

矩阵快速幂刷题系列

来源自http://blog.csdn.net/chenguolinblog/article/details/10309423 hdu 1575 Tr A Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5587    Accepted Submission(s): 4200 Problem Description A为一个方阵,则Tr

HDU 1757 A Simple Math Problem (矩阵快速幂)

[题目链接]:click here~~ [题目大意]: If x < 10 f(x) = x. If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + -- + a9 * f(x-10); 问f(k)%m的值. [思路]:矩阵快速幂,具体思路看代码吧,注意一些细节. 代码: #include<bits/stdc++.h> using namespace std; typedef long long LL; const

Codeforces Round #291 (Div. 2) E - Darth Vader and Tree (DP+矩阵快速幂)

这题想了好长时间,果断没思路..于是搜了一下题解.一看题解上的"快速幂"这俩字,不对..这仨字..犹如醍醐灌顶啊...因为x的范围是10^9,所以当时想的时候果断把dp递推这一方法抛弃了.我怎么就没想到矩阵快速幂呢.......还是太弱了..sad..100*100*100*log(10^9)的复杂度刚刚好. 于是,想到了矩阵快速幂后,一切就变得简单了.就可以把距离<=x的所有距离的点数都通过DP推出来,然后一个快速幂就解决了. 首先DP递推式很容易想到.递推代码如下: for(

POJ 3233 - Matrix Power Series ( 矩阵快速幂 + 二分)

POJ 3233 - Matrix Power Series ( 矩阵快速幂 + 二分) #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; #define MAX_SIZE 30 #define CLR( a, b ) memset( a, b, sizeof(a) ) int MOD = 0; int n, k; st

HDU 4990 Reading comprehension(找规律+矩阵快速幂)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4990 Problem Description Read the program below carefully then answer the question. #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include<iostream> #include

hdu 6198(矩阵快速幂)

number number number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 175    Accepted Submission(s): 119 暴力发现当4 12 33 88 232 和斐波那契数列对比  答案为 第2*k+3个数减1 直接用矩阵快速幂求的F[2*k+3]  然后减1 A=1,B=0; 然后矩阵快速幂2*k

矩阵快速幂 模板与简单讲解

模板 快速幂模板 1 void solve(matrix t,long long o) 2 { 3 matrix e; 4 5 memset(e.a,0,sizeof(e.a)); 6 7 for (int i = 0;i < d;i++) 8 e.a[i][i] = 1; 9 10 while (o) 11 { 12 if (o & 1) 13 { 14 e = mul(e,t); 15 } 16 17 o >>= 1; 18 19 t = mul(t,t); 20 } 21