矩阵幂次之和。

自己想着想着就想到了一个解法,但是还没提交,因为POJ崩了,做了一个FIB的前n项和,也是用了这个方法,AC了,相信是可以得。

提交了,是AC的

http://poj.org/problem?id=3233

我的思路是:

首先原矩阵保留着,然后需要扩大一倍

需要求1--->1的路径数 <= k的,ans = (路径数 = k的) +(路径数 < k)的

等于k的很容易求,就是e^k然后e[1][1]就是答案,那么小于k的,我们需要虚拟一个节点保留着

可以先看看这个http://www.cnblogs.com/liuweimingcprogram/p/6490034.html

然后新增一个节点3,e[1][3] = 1,  e[3][3] = 1是用来求 < k的数目的。

怎么求,比如

这样求到的e[1][1] = 1表明长度是2的有一种情况,但是长度是1的遗漏了,就是1--1本来那条,通过新增一条虚拟边e[1][3]

这样就把1--1原来的那条边保留了下来,

1-->3这条边是专为1服务的,是e[1][1],也就是结尾点是1的情况的总数。所以会有一条e[3][3]的多余边,需要减去1。

而求1-->2的总数的时候,是e[1][2](长度是k的总数) + e[1][4](长度 < k的总数)这里就不会多出一条边了,因为本来的e[1][4] = 0的

这个是真真正正的保留了1--2这条边了。

具体自己画画吧,感觉描述不清楚了。

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
const int maxn = + ;
struct Matrix {
LL a[maxn][maxn];
int row;
int col;
}base;
//应对稀疏矩阵,更快。
struct Matrix matrix_mul(struct Matrix a, struct Matrix b, int MOD) { //求解矩阵a*b%MOD
struct Matrix c = {}; //这个要多次用到,栈分配问题,maxn不能开太大,
//LL的时候更加是,空间是maxn*maxn的,这样时间用得很多,4和5相差300ms
c.row = a.row; //行等于第一个矩阵的行
c.col = b.col; //列等于第二个矩阵的列
for (int i = ; i <= a.row; ++i) {
for (int k = ; k <= a.col; ++k) {
if (a.a[i][k]) { //应付稀疏矩阵,0就不用枚举下面了
for (int j = ; j <= b.col; ++j) {
c.a[i][j] += a.a[i][k] * b.a[k][j];
c.a[i][j] = (c.a[i][j] + MOD) % MOD; //负数取模
}
}
}
}
return c;
}
struct Matrix quick_matrix_pow(struct Matrix ans, struct Matrix base, int n, int MOD) {
//求解a*b^n%MOD
while (n) {
if (n & ) {
ans = matrix_mul(ans, base, MOD);//传数组不能乱传,不满足交换律
}
n >>= ;
base = matrix_mul(base, base, MOD);
}
return ans;
}
int n, k, MOD;
void work() {
base.row = base.col = * n;
for (int i = ; i <= n; ++i) {
for (int j = ; j <= n; ++j) {
cin >> base.a[i][j];
base.a[i][j] %= MOD;
}
}
for (int i = ; i <= n; ++i) {
base.a[i][n + i] = ;
}
for (int i = n + ; i <= * n; ++i) {
base.a[i][i] = ;
}
// for (int i = 1; i <= 2 * n; ++i) {
// for (int j = 1; j <= 2 * n; ++j) {
// printf("%d ", base.a[i][j]);
// }
// printf("\n");
// }
Matrix I = {};
I.row = I.col = * n;
for (int i = ; i <= * n; ++i) {
I.a[i][i] = ;
}
// printf("\n");
I = quick_matrix_pow(I, base, k, MOD);
// for (int i = 1; i <= 2 * n; ++i) {
// for (int j = 1; j <= 2 * n; ++j) {
// printf("%d ", I.a[i][j]);
// }
// printf("\n");
// }
for (int i = ; i <= n; ++i) {
for (int j = ; j <= n; ++j) {
int ans = ;
ans += I.a[i][j];
ans += I.a[i][n + j];
ans %= MOD;
if (i == j) ans = (ans - + MOD) % MOD;
printf("%d ", ans);
}
printf("\n");
}
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
while (cin >> n >> k >> MOD) work();
return ;
}

做了这个题

http://acm.hdu.edu.cn/showproblem.php?pid=5171

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
const int maxn = ;
struct Matrix {
LL a[maxn][maxn];
int row;
int col;
}base;
//应对稀疏矩阵,更快。
struct Matrix matrix_mul(struct Matrix a, struct Matrix b, int MOD) { //求解矩阵a*b%MOD
struct Matrix c = {}; //这个要多次用到,栈分配问题,maxn不能开太大,
//LL的时候更加是,空间是maxn*maxn的,这样时间用得很多,4和5相差300ms
c.row = a.row; //行等于第一个矩阵的行
c.col = b.col; //列等于第二个矩阵的列
for (int i = ; i <= a.row; ++i) {
for (int k = ; k <= a.col; ++k) {
if (a.a[i][k]) { //应付稀疏矩阵,0就不用枚举下面了
for (int j = ; j <= b.col; ++j) {
c.a[i][j] += a.a[i][k] * b.a[k][j];
c.a[i][j] = (c.a[i][j] + MOD) % MOD; //负数取模
}
}
}
}
return c;
}
struct Matrix quick_matrix_pow(struct Matrix ans, struct Matrix base, int n, int MOD) {
//求解a*b^n%MOD
while (n) {
if (n & ) {
ans = matrix_mul(ans, base, MOD);//传数组不能乱传,不满足交换律
}
n >>= ;
base = matrix_mul(base, base, MOD);
}
return ans;
}
const int MOD = ;
int n, k;
int a[ + ];
void work() {
for (int i = ; i <= n; ++i) cin >> a[i];
sort(a + , a + + n);
Matrix I = {};
I.row = I.col = ;
for (int i = ; i <= ; ++i) I.a[i][i] = ;
I = quick_matrix_pow(I, base, k, MOD);
Matrix F = {};
F.row = , F.col = ;
F.a[][] = a[n], F.a[][] = a[n - ];
Matrix b = {};
b.row = b.col = ;
for (int i = ; i <= ; ++i) {
for (int j = ; j <= ; ++j) {
int ans = I.a[i][j];
ans += I.a[i][ + j];
ans %= MOD;
if (i == j) ans = (ans - + MOD) % MOD;
b.a[i][j] = ans;
}
}
// for (int i = 1; i <= 2; ++i) {
// for (int j = 1; j <= 2; ++j) {
// printf("%d ", b.a[i][j]);
// }
// printf("\n");
// }
F = matrix_mul(F, b, MOD);
int ans = F.a[][];
for (int i = ; i <= n; ++i) {
ans = (ans + a[i]) % MOD;
}
cout << ans << endl;
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
base.col = base.row = ;
base.a[][] = , base.a[][] = ;
base.a[][] = , base.a[][] = ;
for (int i = ; i <= ; ++i) {
base.a[i][ + i] = ;
}
for (int i = ; i <= ; ++i) base.a[i][i] = ;
while (cin >> n >> k) work();
return ;
}

Matrix Power Series POJ - 3233 矩阵幂次之和。的更多相关文章

  1. Matrix Power Series(POJ 3233)

    原题如下: Matrix Power Series Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 28044   Acce ...

  2. POJ 3233 Matrix Power Series 【经典矩阵快速幂+二分】

    任意门:http://poj.org/problem?id=3233 Matrix Power Series Time Limit: 3000MS   Memory Limit: 131072K To ...

  3. [ACM] POJ 3233 Matrix Power Series (求矩阵A+A^2+A^3...+A^k,二分求和或者矩阵转化)

    Matrix Power Series Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 15417   Accepted:  ...

  4. POJ 3233 Matrix Power Series --二分求矩阵等比数列和

    题意:求S(k) = A+A^2+...+A^k. 解法:二分即可. if(k为奇)  S(k) = S(k-1)+A^k else        S(k) = S(k/2)*(I+A^(k/2)) ...

  5. 矩阵十点【两】 poj 1575 Tr A poj 3233 Matrix Power Series

    poj 1575  Tr A 主题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1575 题目大意:A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的 ...

  6. Matrix Power Series

    Matrix Power Series 给出矩阵A,求矩阵\(A+A^2+...+A^k\)各个元素\(mod\ yyb\)的值,\(n\leq 30,k\leq 10^9,yyb\leq 10^4\ ...

  7. POJ 3233 Matrix Power Series(矩阵快速幂)

    Matrix Power Series Time Limit: 3000MS Memory Limit: 131072K Total Submissions: 19338 Accepted: 8161 ...

  8. poj 3233 Matrix Power Series(矩阵二分,高速幂)

    Matrix Power Series Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 15739   Accepted:  ...

  9. POJ 3233:Matrix Power Series 矩阵快速幂 乘积

    Matrix Power Series Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 18450   Accepted:  ...

随机推荐

  1. 【转载】ruby 中数组函数示例(1)(转)

    函数名称 说明 示例 &      数组与,返回两数组的交集 [1,2] & [2,3] =>[2]   * 复制数组n次 [1,2]*2       => [1,2,1, ...

  2. TS学习之枚举

    使用枚举可以定义一些有名字的数字常量 enum Test{ one = 1, two, three, four } console.log(Test); /*{ '1': 'one', '2': 't ...

  3. k8s基础 etcd参数

    name 节点名称data-dir 指定节点的数据存储目录listen-peer-urls 监听URL,用于与其他节点通讯listen-client-urls 对外提供服务的地址:比如 http:// ...

  4. java 终端输入小结,输入到数组、文件等(持续更新)

    一:将键盘输入的数存到数组中,数组长度未知 public class Test{ public static void main(String[] args){ Scanner sc = new Sc ...

  5. Learning Python 011 高级特性 2

    Python 高级特性 2 列表生成式 列表生成式就是指类似这样的代码:[x for x in range(1, 11)] >>> L = [x for x in range(1, ...

  6. hbase->Mapreduce->hbase

    Hbase对Mapreduce API进行了扩展,方便Mapreduce任务读写HTable数据. package taglib.customer; import java.io.IOExceptio ...

  7. 32.我的wafBypass之道

    0x01 搞起 当我们遇到一个waf时,要确定是什么类型的?先来看看主流的这些waf,狗.盾.神. 锁.宝.卫士等等...(在测试时不要只在官网测试,因为存在版本差异导致规则库并不一致) 1.云waf ...

  8. AndroidMainfest.xml文件解释

    AndroidManifest.xml是每个android程序中必须的文件.它位于application的根目录,描述了package中的全局数据,包括了package中暴露的组件(activitie ...

  9. C# 用委托有什么好处? 它起什么作用?

    什么是委托 首先要知道什么是委托,用最通俗易懂的话来讲,你就可以把委托看成是用来执行方法(函数)的一个东西. 如何使用委托 在使用委托的时候,你可以像对待一个类一样对待它.即先声明,再实例化.只是有点 ...

  10. C# 写 LeetCode Medium #2 Add Two Numbers

    2. Add Two Numbers You are given two non-empty linked lists representing two non-negative integers. ...