HDOJ 2294 - Pendant
2012-07-16 15:23
218 查看
Description
有个高富帅,要送个很装逼的吊坠给他女朋友。
他有k种珠子,然后要串成一个 珠子个数小于等于n 的链子。
因为要够装逼,所以这k种珠子都必须要用到。
好了,输入n和k。
输出他可以做出多少种不一样的项链。
Type
Matrix Multiplication
Quick Power
Analysis
一看又是爽歪歪的递推题。
我们来考虑如何递推出。
设f(x, y)为前x个位置,搞了y种不同的珠子。
然后我们考虑f(x, y)和f(x – 1, ...)关系。
而前后的关系,就差在第x个位置,要放什么类型的珠子。
我们可以放前面x – 1个位置已经放过的珠子,有y种颜色可以选。
那么就有 f(x – 1, y) * y种。
也可以放前面x – 1个位置还没放过的珠子,有k- (y – 1)种颜色可以选。
那么就有 f(x – 1, y – 1) * (k – y + 1) 种。
所以我们就得到递推公式 —— f(x, y) = f(x – 1, y) * y + f(x – 1, y – 1) * (k – y + 1)
好了,有了递推公式就碉堡了,剩下的就是矩阵乘法和快速幂。
当然,也要注意一些小的细节。
我们所求的不是f(x, y),而是f(1, y) ~ f(x, y)的总和(因为珠子个数是小于等于n嘛)。
因此我们需要在矩阵的解向量中,增加一项sum(x – 1),且 sum(x – 1) = sum(x – 2) + f(x - 1, y)。
这题对1234567891取余,有点那啥。
在矩阵乘法中,我们通常是每一个矩阵元素计算完后,再去取余,这样可以减少大量运算时间
(如果你不是这样的,那我告诉你,真的省很多)。
而这题由于这个除数真TMD的大,矩阵相乘的时候,两个元素相乘然后加加加加加...
最后你懂的,就超过long long的范围,溢出了,囧。
深一步讲,因为long long = int * int,而除数过于接近int。
导致我们计算的数接近于int * int * order(矩阵的阶),就爆了。
好吧,怎么办?
一种办法是用unsigned long long,的确可以A,速度还蛮快。
当然如果感觉不够妥妥的,可以每次在计算的时候,做完int * int马上mod,就不会悲剧啦。
(如果你现在不知道我在讲什么,那就等到你在写矩阵相乘函数的时候,你就懂了~)
Solution
// HDOJ 2294 // pendant // by A Code Rabbit #include <cstdio> #include <cstring> const int MAXO = 33; const int MOD = 1234567891; template <typename T> struct Matrix { T e[MAXO][MAXO]; int o; Matrix(int ord) { memset(e, 0, sizeof(e)); o = ord; } Matrix operator*(const Matrix& one) { Matrix res(o); for (int i = 0; i < o; i++) for (int j = 0; j < o; j++) for (int k = 0; k < o; k++) res.e[i][j] += e[i][k] * one.e[k][j]; return res; } Matrix operator%(int mod) { for (int i = 0; i < o; i++) for (int j = 0; j < o; j++) e[i][j] %= mod; return *this; } }; template <typename T> T QuickPower(T rdx, int exp, int mod) { T res = rdx; exp--; while (exp) { if (exp & 1) res = res * rdx % mod; exp >>= 1; rdx = rdx * rdx % mod; } return res; } int n, k; int main() { int tot_case; scanf("%d", &tot_case); while (tot_case--) { // Input. scanf("%d%d", &n, &k); // Sovle. Matrix<unsigned long long> mat_one(k + 1); mat_one.e[0][0] = 1; mat_one.e[k][0] = 1; for (int i = 1; i < k + 1; ++i) { mat_one.e[i][i] = i; if (i > 1) mat_one.e[i - 1][i] = k - i + 1; } Matrix<unsigned long long> mat_ans = QuickPower(mat_one, n, MOD); // Output. printf("%d\n", k * mat_ans.e[1][0] % MOD); } return 0; }
相关文章推荐
- HDOJ 2294 - Pendant(DP+矩阵快速幂)
- hdu 2294 Pendant (dp+矩阵快速幂)
- HDU - 2294 Pendant (DP滚动数组降维+矩阵高速功率)
- hdu 2294 Pendant(矩阵乘法)
- HDU 2294 Pendant
- long long 与 int(HDOJ 2294)
- hdu 2294 pendant
- hdu 2294 Pendant (动态规划+矩阵) 解题报告
- HDU - 2294 Pendant (DP滚动数组降维+矩阵快速幂)
- HDU 2294 Pendant(DP+矩阵)
- HDU 2294 Pendant
- hdu 2294 Pendant
- HDU 2294 Pendant
- HDU 2294 Pendant (DP+矩阵快速幂降维)
- hdoj2041
- 【HDOJ】1271 整数对
- HDOJ 2674 N!Again (同余定理)
- HDOJ(HDU) 1678 Shopaholic
- HDOJ 1533.Going Home 最小费用最大流
- HDOJ_ACM_Max Sum