首页 > 代码库 > HDU4565-So Easy!(共轭运用+矩阵快速幂)
HDU4565-So Easy!(共轭运用+矩阵快速幂)
题目链接
题意:
求解
思路:
记(a+b√)n 为An ,配项
Cn=An+Bn=(a+b√)n+(a?b√)n
两项恰好共轭,所以Cn 是整数。又根据限制条件
(a?1)2<b<a2?0<a?b√<1?0<(a?b√)n<1?Bn<1
也就是说Cn=?An?
Sn=(Cn)%m
求Cn 的方法是递推。 对Cn 乘以(a+b√)+(a?b√)
于是
Cn+1=2aCn?(a2?b)Cn?1
把这个递推式写成矩阵形式
[Cn+1Cn]=[2a1?(a2?b)0][CnCn?1]
于是就可以用矩阵快速幂来做了
[Cn+1Cn]=[2a1?(a2?b)0]n[C1C0]
公式推倒链接
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; typedef long long ll; //typedef __int64 ll; ll a, b, n, m; struct mat{ ll s[2][2]; mat() { memset(s, 0, sizeof(s)); } mat operator * (const mat& c) { mat ans; memset(ans.s, 0, sizeof(ans.s)); for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) ans.s[i][j] = (s[i][0] * c.s[0][j] + s[i][1] * c.s[1][j]) % m; return ans; } void put() { for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) printf("%lld ", s[i][j]); printf("\n"); } } }c; void init() { c.s[0][0] = 2 * a; c.s[0][1] = b - a * a; c.s[1][0] = 1; c.s[1][1] = 0; } mat pow_mod(ll k) { if (k == 1) return c; mat a = pow_mod(k / 2); mat ans = a * a; if (k % 2) ans = ans * c; return ans; } int main() { while (scanf("%lld%lld%lld%lld", &a, &b, &n, &m) != EOF) { init(); ll s1, s2; s1 = (a * 2) % m; double t = pow(a + sqrt((double)b), 2); s2 = (ll)ceil(t) % m; if (n == 1) printf("%lld\n", s1); else if (n == 2) printf("%lld\n", s2); else { mat ans = pow_mod(n - 2); ll a = (((ans.s[0][0] * s2 % m ) + m) % m + ((ans.s[0][1] * s1 % m ) + m)% m); printf("%lld\n", a % m); } } return 0; }
HDU4565-So Easy!(共轭运用+矩阵快速幂)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。