ZOJ - 2853 Evolution

题意:给你N个数,1~N分别为num[i],  以及T个 (i,j,P)

对于每组(i,j,P),让你将  num[i] 减去 P*num[i]  再把 P*num[i] 加到 num[j] 上。T个操作同时完成。

这T个操作执行M次(M<1e5)。求最后一个点的值。

题解:将N个值排成一排放到矩阵 1*n B里,我们可以构造一个 n*n 矩阵A,使得 B*A (一个 1*n 的矩阵)的第i列为操作一次后的 第i个数的值。然后就能矩阵快速幂了!

    如何构造? 一列一列构造。

    A的第i列会从上到下依次乘完B,然后加起来作为第i个数的值。于是我们从上到下依次填上p(j,i)(即从j转移到i的数值,j=1 to n,这样就把所有转移到i的数值都加起来了。)

      现在我们考虑如何表示第i个数值转移的值,注意到A的第i行为p(i,j)(j = 1 to n) 就是所有从i转移到其它数的概率,于是我们对这一行求和得sum,然后将1-sum填入(i,i)。

    这样就构造完成了。

    简单说就是线性代数

坑:1.visual studio struct里不能定义a[200][200]否则会报错overflow,但oj上能过。

  2.四舍五入不能round,用.0f.

#define _CRT_SECURE_NO_WARNINGS
#include<cstring>
#include<cctype>
#include<cstdlib>
#include<iomanip>
#include<cmath>
#include<cstdio>
#include<string>
#include<stack>
#include<ctime>
#include<list>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<sstream>
#include<fstream>
#include<iostream>
#include<functional>
#include<algorithm>
#include<memory.h>
//#define INF 0x3f3f3f3f
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
#define rep(i,t,n)  for(int i =(t);i<=(n);++i)
#define per(i,n,t)  for(int i =(n);i>=(t);--i)
#define mp make_pair
#define pb push_back
#define mmm(a,b) memset(a,b,sizeof(a))
//std::ios::sync_with_stdio(false);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
void smain();
#define ONLINE_JUDGE
int main() {
    ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    FILE *myfile;
    myfile =freopen("C:\\Users\\SuuTT\\Desktop\\test\\in.txt", "r", stdin);
    if (myfile == NULL)
        fprintf(stdout, "error on input freopen\n");
    /*FILE *outfile;
    outfile= freopen("C:\\Users\\SuuTT\\Desktop\\test\\out.txt", "w", stdout);
    if (outfile == NULL)
        fprintf(stdout, "error on output freopen\n");*/
    long _begin_time = clock();
#endif
    smain();
#ifndef ONLINE_JUDGE
    long _end_time = clock();
    printf("time = %ld ms.", _end_time - _begin_time);
#endif
    return 0;
}
int dir[4][2] = { 1,0,0,1,-1,0,0,-1 };
const int maxn = 2e2 + 5;
int n, m;
struct matrix {
    double mat[maxn][maxn];
    int r, c;
    matrix(int rr, int cc) {
        rep(i, 1, rr)rep(j, 1, cc) mat[i][j] = 0;
        r = rr, c = cc;
    }
    void init(int rr, int cc,int val) {
        rep(i, 1, rr)rep(j, 1, cc) mat[i][j] = val;
        r = rr, c = cc;
    }
    matrix friend operator *(matrix a, matrix b) {
        matrix ans(a.r, b.c);
        if (a.c != b.r) {
            cout << "ERROR"; return ans;
        }
        rep(i,1,a.r)rep(j,1,b.c)rep(k, 1, a.c) { ans.mat[i][j] += a.mat[i][k] * b.mat[k][j]; }
        return ans;
    }
};
matrix a(maxn, maxn), b(1, maxn);
matrix temp(maxn,maxn);
double self[maxn];
void Run() {

}
void quickpow(matrix a, int n) {
    
    temp.init(a.r, a.c, 0);
    rep(i, 1, a.r) temp.mat[i][i] = 1;
    while (n) {
        if (n & 1) temp = temp*a;
        a = a*a; n >>= 1;
    }
    
}
void smain() {
    while (cin >> n>>m)
    {
        if (!n && !m)break;
        a.init(n, n,0);
        b.init(1,n,0);
        
        fill(self, self + 1 + n, 1.0);
        rep(i, 1, n)cin >> b.mat[1][i];
        int t; cin >> t;
        while (t--) {
            int x, y; double p;
            cin >> x >> y >> p; x++, y++;
            a.mat[x][y] = p;
            self[x] -= p;
        }
        rep(i, 1, n)a.mat[i][i] = self[i];

        quickpow(a, m);
        b = b*temp;
        //cout << round(b.mat[1][n])<<endl;
        printf("%.0f\n", b.mat[1][n]);
    }
}
/*

2 30
100 20
1
0 1 0.5
4 100
1000 2000 3000 0
3
0 1 0.19
1 2 0.05
0 2 0.67
*/

        

猜你喜欢

转载自www.cnblogs.com/SuuT/p/9005133.html
ZOJ