矩阵幂次之和。

自己想着想着就想到了一个解法,但是还没提交,因为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. %.*s, printf

    %.*s_百度搜索 c语言%.*s是什么_百度知道 *用来指定宽度,对应一个整数 .(点)与后面的数合起来 是指定必须输出这个宽度,如果所输出的字符串长度大于这个数,则按此宽度输出,如果小于,则输出实 ...

  2. URL网址规范化

    网址URL规范化(URL canonicalization)是近一年来在Google搜索结果中出现的一个很大的问题.它指的是搜索引擎挑选最好的URL网址作为真正网址的过程.举例来说,下面这几个URL一 ...

  3. struts 文件上传示例

    import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io ...

  4. Angular10 组件之间的通讯

    1 父组件和子组件之间的通讯 2 利用中间组件实现两个组件之间的通讯 3 利用服务实现两个组件之间的通讯 2017年8月26日20:09:13 待更新... 1 组件之间的关系图 1.1 父子关系 1 ...

  5. javascript 数组中出现的次数最多的元素

    javascript 数组中出现的次数最多的元素 var arr = [1,-1,2,4,5,5,6,7,5,8,6]; var maxVal = arr[0]; // 数组中的最大值 var min ...

  6. kingadmin

    kingadmin 是一个模拟 Django admin 开发的后台管理系统,可以用来嵌套在其他的项目中作为单独的 app 程序存在. 执行流程 1.项目启动,开始执行 app_setup.py 文件 ...

  7. 关于PHP在企业级开发领域的访谈——企业级开发,PHP准备好了吗?

    关于PHP在企业级开发领域的访谈 ——企业级开发,PHP准备好了吗? 转自:http://www.nowamagic.net/librarys/veda/detail/256 虽然PHP是Web应用开 ...

  8. 利用css实现鼠标经过元素,下划线由中间向两边展开

    代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...

  9. 【leetcode 76. 最小覆盖子串】解题报告

    思路:滑动窗口思想 方法一:滑动窗口 string minWindow(string s, string t) { // 1.tdict记录T中每个字母与字母个数 // 2.维护一个滑动窗口字母的计数 ...

  10. Wannafly summer camp Day2I(思维)

    #include<bits/stdc++.h>using namespace std;int a[1000007],b[1000007],c[1000007];int find_max(i ...