您的位置:首页 > 产品设计 > UI/UE

hdu 2604 Queuing dp找规律 然后矩阵快速幂。坑!!

2017-02-26 23:52 239 查看
http://acm.hdu.edu.cn/showproblem.php?pid=2604

这题居然O(9 * L)的dp过不了,TLE, 更重要的是找出规律后,O(n)递推也过不了,TLE,一定要矩阵快速幂。然后立马GG.

用2代表m,1代表f。设dp[i][j][k]表示,在第i位,上一位站了的人是j,这一位站的人是k,的合法情况。

递推过去就是,如果j是1,k是2,那么这一位就只能放一个2,这个时猴dp[i][k][2] += dp[i - 1][j][k];

其他情况分类下就好,然后乖乖超时吧。注意L = 1的时候,直接是2

或者直接dfs搜也行。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
int L, MOD;
const int maxn = 8;
int ans[] = {0, 2, 4, 6, 9, 15, 25};
struct Matrix {
LL a[maxn][maxn];
int row;
int col;
};
//应对稀疏矩阵,更快。
struct Matrix matrix_mul(struct Matrix a, struct Matrix b, int MOD) { //求解矩阵a*b%MOD
struct Matrix c = {0};  //这个要多次用到,栈分配问题,maxn不能开太大,
//LL的时候更加是,空间是maxn*maxn的,这样时间用得很多,4和5相差300ms
c.row = a.row; //行等于第一个矩阵的行
c.col = b.col; //列等于第二个矩阵的列
for (int i = 1; i <= a.row; ++i) {
for (int k = 1; k <= a.col; ++k) {
if (a.a[i][k]) { //应付稀疏矩阵,0就不用枚举下面了
for (int j = 1; 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 & 1) {
ans = matrix_mul(ans, base, MOD);//传数组不能乱传,不满足交换律
}
n >>= 1;
base = matrix_mul(base, base, MOD);
}
return ans;
}

void work() {
if (L <= 6) {
printf("%d\n", ans[L] % MOD);
return;
}
struct Matrix t1 = {0};
t1.row = 1, t1.col = 5;
t1.a[1][1] = ans[5], t1.a[1][2] = ans[4], t1.a[1][3] = ans[3], t1.a[1][4] = ans[2], t1.a[1][5] = ans[1];

struct Matrix t2 = {0};
t2.row = t2.col = 5;
t2.a[1][2] = 1;
t2.a[2][1] = t2.a[2][3] = 1;
t2.a[3][1] = t2.a[3][4] = 1;
t2.a[4][1] = 2, t2.a[4][5] = 1;
t2.a[5][1] = 1;

struct Matrix res = quick_matrix_pow(t1, t2, L - 5, MOD);
printf("%d\n", res.a[1][1]);
}

int main() {
#ifdef local
freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
while (scanf("%d%d", &L, &MOD) != EOF) work();
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: