hdu 2971 Tower(注意负数的取模处理)
2010-07-18 22:00
260 查看
先假设a2 = t, 题目给定了递推关系:An = 2 * t * An-1 - An-2 (n > 2),初值A1 = 1, A2 = t;题目要求Sn = An ^ 2 + An-1 ^ 2 + ... + A1 ^ 2。
反复应用递推关系得到:
然后Sn-1利用相同的方式展开,把4tAn-2An-3约去,得到:
这样就比较容易得出Sn的通项:
当初这个题目之所以没想到这种方法,就是因为一看到递推关系,就想着用一般解方程的方法去求解通项,思维被局限了,其实用简单的方式就可以推出来的。以后对于一个问题,应该从多个方面去想,不能想当然啊。想起最近看到的一段话,以此自勉:
正则表达式非常强大,但是它并不能为每一个问题提供正确的解决方案。你应该学习足够多的知识,以辨别什么时候它们是合适的,什么时候它们会解决你的问题,什么时候它们产生的问题比要解决的问题还要多。
一些人,遇到一个问题时就想:“我知道,我将使用正则表达式。”现在他有两个问题了。——Jamie Zawinski
http://www.cppblog.com/sdfond/archive/2010/03/12/109521.html?opt=admin
反复应用递推关系得到:
然后Sn-1利用相同的方式展开,把4tAn-2An-3约去,得到:
这样就比较容易得出Sn的通项:
当初这个题目之所以没想到这种方法,就是因为一看到递推关系,就想着用一般解方程的方法去求解通项,思维被局限了,其实用简单的方式就可以推出来的。以后对于一个问题,应该从多个方面去想,不能想当然啊。想起最近看到的一段话,以此自勉:
正则表达式非常强大,但是它并不能为每一个问题提供正确的解决方案。你应该学习足够多的知识,以辨别什么时候它们是合适的,什么时候它们会解决你的问题,什么时候它们产生的问题比要解决的问题还要多。
一些人,遇到一个问题时就想:“我知道,我将使用正则表达式。”现在他有两个问题了。——Jamie Zawinski
http://www.cppblog.com/sdfond/archive/2010/03/12/109521.html?opt=admin
]/* 又学了一招了,矩阵中有负数的时候,取模取了之后 if(r.num[i][j] < 0) r.num[i][j] += mod; 就是因为这里一直错,于是开始乱七不遭地改,郁闷是后来xwc提醒说要考虑 还有就是很奇怪,hdu oj 对于_int64 的要求很不高的,今天试了好多,感觉没有什么不可以的 记得zoj是要用_int64 % I64d 的,有些oj long long int %lld */ #include <iostream> #include <cstdio> #include <cstring> using namespace std; struct Mat { _int64 num[4][4]; Mat() { for(int i = 0; i < 4; i++) for(int j = 0; j < 4; j++) num[i][j] = 0; } }; Mat mul(Mat a, Mat b, _int64 mod) { Mat r; for(int i = 0; i < 4; i++) for(int j = 0; j < 4; j++) r.num[i][j] = 0; for(int i = 0; i < 4; i++) for(int k = 0; k < 4; k++) { if(a.num[i][k] == 0) continue; for(int j = 0; j < 4; j++) { if(b.num[k][j] == 0) continue; r.num[i][j] =(r.num[i][j] + a.num[i][k] * b.num[k][j]) % mod; if(r.num[i][j] < 0) r.num[i][j] += mod; } } return r; } Mat mal(Mat a, Mat b, _int64 n, _int64 mod) { while(n) { if(n & 1) { b = mul(a , b, mod); n--; } else { a = mul(a, a, mod); n >>= 1; } } return b; } int main() { int t; //cin >> t; scanf("%d", &t); while(t--) { _int64 a2, n, mod; //cin >> a2 >> n >> mod; scanf("%I64d %I64d %I64d", &a2, &n, &mod); _int64 sum2 = (a2 * a2 + 1) % mod; _int64 a3 = (2 * a2 * a2 - 1) % mod; _int64 a4 = (2 * a2 * a3 - a2) % mod; if(n == 1) { cout << "1" << endl; continue; } if(n <= 4) { if(n == 3) sum2 += a3 * a3; if(n == 4) sum2 += a3 * a3 + a4 * a4; cout << sum2 % mod << endl; continue; } Mat init, unit; for(int i = 0; i < 4; i++) for(int j = 0; j < 4; j++) { init.num[i][j] = 0; unit.num[i][j] = 0; } init.num[0][0] = (4 * a2 * a2) % mod; // 这里的取模我一开始是加了的,后来改的时候又去,郁闷 init.num[0][1] = (2 - 8 * a2 * a2) % mod; init.num[0][2] = (4 * a2 * a2) % mod; init.num[0][3] = -1; init.num[1][0] = 1; init.num[2][1] = 1; init.num[3][2] = 1; unit.num[0][0] = (sum2 + a3 * a3 + a4 * a4) % mod; unit.num[1][0] = (sum2 + a3 * a3) % mod; unit.num[2][0] = sum2 % mod; unit.num[3][0] = 1; Mat ans; ans = mal(init, unit, n - 4, mod); printf("%I64d/n", ans.num[0][0]); //cout << ans.num[0][0] % mod << endl; } }
相关文章推荐
- hdu 2971 Tower(矩阵快速幂)
- hdu 2971 Tower
- HDU 1176 免费馅饼 (类似于数塔DP的题目,注意边界条件,细节处理)
- HDU 2971 Tower(构造矩阵)
- HDU 2971 Tower
- HDU 2971 Tower 构造矩阵
- Hdu 2971 Tower
- hdu 2971 Tower(*矩阵乘法)
- hdu 2971 Tower(矩阵快速幂)
- [矩阵乘法 + 矩阵构造] HDU 2971 Tower
- hdu 2971 Tower 矩阵
- CERC_2008_Tower(hdu 2971)
- HDU 2971 Tower (矩阵快速幂)
- c++和c#求摸操作符号%的注意问题,是负数的情况
- 使用C#处理文本内容注意
- HDU 1430 DFS + 康托展开 + 映射处理 +预处理!
- 手工配置tnsnames.ora文件注意事项——谨慎处理空格
- java异常处理的六个注意事项
- Qt中如何禁掉所有UI操作以及注意事项(处理各个widget的eventFilter这一层,但是感觉不好,为什么不使用QApplication呢)
- 图像处理与识别的算法中若有非线性变换,那么请一定注意归一化的处理会影响结果!