题意:给你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 "); /*FILE *outfile; outfile= freopen("C:\Users\SuuTT\Desktop\test\out.txt", "w", stdout); if (outfile == NULL) fprintf(stdout, "error on output freopen ");*/ 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 ", 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 */