UVALive 5112 - Sales Prediction

封装了矩阵类
比赛做得很郁闷,为什么别人写得很长、很罗嗦的代码可以过题,而我的总是过不了呢?...

/*
* Author: rush
* Created Time: 2011年01月05日 星期三 19时39分08秒
* File Name: icpc/20100105/E2.cpp
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#define out(v) cout << #v << ": " << (v) << endl
using namespace std;
typedef long long LL;
const LL MOD = 1000000007LL;

#define FOR(i, n) for (int i = 1; i <= (n); ++i)
typedef vector<LL> Vec;
struct Mat {
LL mat[10][10], n;
Mat(int _n): n(_n) { FOR(i, n) FOR(j, n) mat[i][j] = 0; }
Mat one() const {
Mat ans(n);
FOR(i, n) FOR(j, n) ans[i][j] = (i == j);
return ans;
}
LL* operator[](int x) {
return mat[x];
}
Mat operator *(Mat R) {
Mat ans(n);
FOR(i, n) FOR(j, n) {
ans[i][j] = 0;
FOR(k, n) ans[i][j] = (ans[i][j] + (LL)mat[i][k] * R[k][j] % MOD) % MOD;
}
return ans;
}
Vec operator *(Vec R) {
Vec ans(10, 0);
FOR(i, n) {
ans[i] = 0;
FOR(k, n) ans[i] = (ans[i] + (LL)mat[i][k] * R[k] % MOD) % MOD;
}
return ans;
}
Mat operator +(Mat R) {
Mat ans(n);
FOR(i, n) FOR(j, n) ans[i][j] = ((LL)mat[i][j] + R[i][j]) % MOD;
return ans;
}
Mat pow(LL k) {
Mat ans = one(), x = *this;
while (k) {
if (k & 1) ans = ans * x;
k >>= 1;
if (k) x = x * x;
}
return ans;
}
Mat sumpow(LL k) {
// I + M + M^2 + ... + M^k
if (k == 0) { return one(); }
if (k % 2 == 1) {
Mat mid = sumpow(k / 2);
return mid + mid * pow(k / 2 + 1);
}
return sumpow(k - 1) * (*this) + one();
}
};

int T;
int N, R, K;
Vec S(10, 0), a(10, 0);

int main()
{
scanf("%d", &T);
while (T--) {
scanf("%d%d%d", &N, &R, &K);
FOR(i, R) scanf("%lld", &S[i]);
for (int i = R; i >= 1; --i) scanf("%lld", &a[i]);

Mat A(R);
FOR(i, R - 1) A[i][i + 1] = 1;
FOR(j, R) A[R][j] = a[j];

Vec C = A.pow(K - 1) * S;
Vec D = A.pow(K).sumpow(N - 1) * C;
printf("%lld\n", D[1]);
}
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值