POJ3735 Training little cats 矩陣快速冪 + 矩陣快速冪優化
阿新 • • 發佈:2020-07-21
有n只貓,每隻貓初始石刻沒糖果。 進行m次重複的k次操作。
g i 給第i只貓一個糖果
s i j 交換第i只貓和第j只貓的糖果
c i 吃掉第i只貓的所有糖果
m <=1e9 明顯是用矩陣快速冪處理。 難點在於建立轉移矩陣。
注意到只需對單位矩陣操作。對於n只貓建立 n+1 * 1 的矩陣,多的一行存放 1 用來轉移。
g i ,即對單位矩陣 E的第i行第n + 1列 set 為1
s i j 即對單位矩陣的i j 行交換
c i 即對單位矩陣的第i行clear
如此就可以矩陣快速冪了 。
注意到矩陣是稀疏矩陣,考慮優化。
#pragma warning(disable:4996) #include<iostream> #include<algorithm> #include<bitset> #include<tuple> #include<unordered_map> #include<fstream> #include<iomanip> #include<string> #include<cmath> #include<cstring> #include<vector> #include<map> #include<set> #include<list> #include<queue> #include<stack> #include<sstream> #include<cstdio> #include<ctime> #include<cstdlib> #define INF 0x3f3f3f3f #define inf 0x7FFFFFFF #define MOD 998244353 #define moD 1000000003 #define pii pair<int,string> #define eps 1e-8 #define equals(a,b) (fabs(a-b)<eps) #definebug puts("bug") #define re register #define fi first #define se second const int maxn = 1e6 + 5; const double Inf = 10000.0; const double PI = acos(-1.0); typedef long long ll; typedef unsigned long long ull; using namespace std; struct Mat { ll m[105][105]; }; Mat E; ll n, m, k; void init(int n) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) if(i == j) E.m[i][j] = 1; } } Mat mul(const Mat& a, const Mat& b) { Mat c; for (int i = 0; i < n + 1; i++) for (int j = 0; j < n + 1; j++) c.m[i][j] = 0; for (int i = 0; i < n + 1; i++) { for (int k = 0; k < n + 1; k++) { if(a.m[i][k]) for (int j = 0; j < n + 1; j++) c.m[i][j] = (c.m[i][j] + a.m[i][k] * b.m[k][j] ) ; } } return c; } Mat mult(const Mat& a, const Mat& b) { Mat c; for (int i = 0; i < n + 1; i++) { for (int j = 0; j < 1; j++) { c.m[i][j] = 0; for (int k = 0; k < n + 1; k++) c.m[i][j] = (c.m[i][j] + a.m[i][k] * b.m[k][j] ) ; } } return c; } Mat ans; Mat base; Mat quickPower(Mat a, ll b) { ans = E; base = a; while (b) { if (b & 1) ans = mul(ans, base); base = mul(base, base); b >>= 1; } return ans; } Mat q; int main() { init(105 + 1); while (scanf("%lld%lld%lld", &n, &m, &k), n || m || k) { Mat s; q = E; char op[3]; int x, y; for (int i = 0; i < k; i++) { scanf("%s", op); if (strcmp(op, "g") == 0) { scanf("%d", &x); Mat tmp = E; tmp.m[x - 1][n] = 1; q = mul(tmp, q); } else if (strcmp(op, "s") == 0) { scanf("%d%d", &x, &y); Mat tmp = E; tmp.m[x - 1][x - 1] = 0; tmp.m[x - 1][y - 1] = 1; tmp.m[y - 1][y - 1] = 0; tmp.m[y - 1][x - 1] = 1; q = mul(tmp, q); } else { scanf("%d", &x); Mat tmp = E; tmp.m[x - 1][x - 1] = 0; q = mul(tmp, q); } } q = quickPower(q, m); for (int i = 0; i < n; i++) s.m[i][0] = 0; s.m[n][0] = 1; q = mult(q, s); for (int i = 0; i < n; i++) printf("%lld ", q.m[i][0]); puts(""); } }