hdu 4565 推倒公式+矩阵快速幂

2024-09-09 15:58

本文主要是介绍hdu 4565 推倒公式+矩阵快速幂,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题意

求下式的值:

Sn= (a+b)n%m

其中:

0<a,m<215
0<b,n<231
(a1)2<b<a2

解析

令:

An=(a+b)n

Bn=(ab)n

Cn=An+Bn

因为: (a1)2<b<a2

所以: 0<ab<1

所以: 0<(ab)n<1

即: Bn<1

也就是说, Cn= An  Sn=Cn

因此,求 Cn 就行了。

Cn 两边同时乘以 A1+B1

Cn[(a+b)+(ab)]

=[(a+b)n+(ab)n][(a+b)+(ab)]

=(a+b)n+1+(ab)n+1+(a+b)n(ab)+(ab)n(a+b)

=Cn+1+(a2b)(a+b)n1+(a2b)(ab)n1

=Cn+1+(a2b)Cn1

所以:

Cn+1=2aCn(a2b)Cn1

写成矩阵形式:

[Cn+1 Cn ]=[2a1(a2b)0][C1C0]

至此,公式推导完毕,用快速幂求解就行了。

代码

#pragma comment(linker, "/STACK:1677721600")
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cassert>
#include <iostream>
#include <algorithm>
#define pb push_back
#define mp make_pair
#define LL long long
#define lson lo,mi,rt<<1
#define rson mi+1,hi,rt<<1|1
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a,b) memset(a,b,sizeof(a))
#define FIN freopen("in.txt", "r", stdin)
#define FOUT freopen("out.txt", "w", stdout)using namespace std;
const double eps = 1e-8;
const double ee = exp(1.0);
const int inf = 0x3f3f3f3f;
const int maxn = 1e3 + 10;
const double pi = acos(-1.0);
const LL iinf = 0x3f3f3f3f3f3f3f3f;int readT()
{char c;int ret = 0,flg = 0;while(c = getchar(), (c < '0' || c > '9') && c != '-');if(c == '-') flg = 1;else ret = c ^ 48;while( c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c ^ 48);return flg ? - ret : ret;
}int mod;
typedef vector<LL> vec;
typedef vector<vec> mat;mat mul(mat &A, mat &B)
{mat C(A.size(), vec(B[0].size()));for (int i = 0; i < A.size(); i++){for (int k = 0; k < B.size(); k++){for (int j = 0; j < B[0].size(); j++){C[i][j] = ((C[i][j] + A[i][k] * B[k][j]) % mod  + mod)% mod;}}}return C;
}mat pow(mat A, LL n)
{mat B(A.size(), vec(A.size()));for (int i = 0; i < A.size(); i++){B[i][i] = 1;}while (0 < n){if (n & 1)B = mul(B, A);A = mul(A, A);n >>= 1;}return B;
}int main()
{
#ifdef LOCALFIN;
#endif // LOCALLL a, b, n;while (cin >> a >> b >> n >> mod){mat A(2, vec(2));A[0][0] = 2 * a;  A[0][1] = b - a * a;A[1][0] = 1;      A[1][1] = 0;A = pow(A, n - 1);LL ans = ((2 * a * A[0][0] + 2 * A[0][1]) % mod + mod )% mod;printf("%d\n", ans);}return 0;
}

这篇关于hdu 4565 推倒公式+矩阵快速幂的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1151621

相关文章

shell脚本快速检查192.168.1网段ip是否在用的方法

《shell脚本快速检查192.168.1网段ip是否在用的方法》该Shell脚本通过并发ping命令检查192.168.1网段中哪些IP地址正在使用,脚本定义了网络段、超时时间和并行扫描数量,并使用... 目录脚本:检查 192.168.1 网段 IP 是否在用脚本说明使用方法示例输出优化建议总结检查 1

Rust中的Option枚举快速入门教程

《Rust中的Option枚举快速入门教程》Rust中的Option枚举用于表示可能不存在的值,提供了多种方法来处理这些值,避免了空指针异常,文章介绍了Option的定义、常见方法、使用场景以及注意事... 目录引言Option介绍Option的常见方法Option使用场景场景一:函数返回可能不存在的值场景

电脑桌面文件删除了怎么找回来?别急,快速恢复攻略在此

在日常使用电脑的过程中,我们经常会遇到这样的情况:一不小心,桌面上的某个重要文件被删除了。这时,大多数人可能会感到惊慌失措,不知所措。 其实,不必过于担心,因为有很多方法可以帮助我们找回被删除的桌面文件。下面,就让我们一起来了解一下这些恢复桌面文件的方法吧。 一、使用撤销操作 如果我们刚刚删除了桌面上的文件,并且还没有进行其他操作,那么可以尝试使用撤销操作来恢复文件。在键盘上同时按下“C

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

hdu 3790 (单源最短路dijkstra)

题意: 每条边都有长度d 和花费p,给你起点s 终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。 解析: 考察对dijkstra的理解。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstrin