zzuli 2180 GJJ的日常之沉迷数学【矩阵快速幂 || 逆元】
来源:互联网 发布:淘宝流量来源怎么获取? 编辑:程序博客网 时间:2024/05/20 15:59
Description
GJJ每天都要膜拜一发数学大佬,因为GJJ的数学太差了。这不,GJJ又遇到难题了,他想求助WJJ,但是WJJ这几天忙于追妹子,哪有时间给他讲题, 于是GJJ求助于热爱ACM的你,Acmer们能帮帮他吗?问题是求: k^0 + k^1 +…+ k^(n) mod p (0 < k < 100, 0 <= n <= 10^9, p = 1000000007)
例如:6^0 + 6^1 +…+ 6^(10) mod 1000000007 (其中k = 6, n = 10, p = 1000000007)
Input
输入测试数据有多组,每组输入两个整数k, n
Output
每组测试数据输出:Case #: 计算结果
Sample Input
2 1
6 10
Sample Output
Case 1: 3
Case 2: 72559411
思路:
我是构造矩阵快速幂写出来的,题解用的逆元+快速幂;
一个2 * 2矩阵,左上部分是K,右上和右下是1,左下是0的一个初始矩阵,只要求初始矩阵n+1次幂后,右上部分就是答案(0秒过题);
#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;typedef long long LL;const LL mod = 1e9 + 7;LL n, m;struct mat{ LL mapp[2][2];};mat mat_mul(mat A, mat B) { mat C; memset(C.mapp, 0, sizeof(C.mapp)); for(int i = 0; i < 2; i++) { for(int j = 0; j < 2; j++) { for(int k = 0; k < 2; k++) { C.mapp[i][k] = (C.mapp[i][k] + (A.mapp[i][j] % mod) * (B.mapp[j][k] % mod)) % mod; } } } return C;}LL mat_pow(mat A) { mat ans; ans.mapp[0][0] = ans.mapp[1][1] = 1; ans.mapp[1][0] = ans.mapp[0][1] = 0; while(n) { if(n & 1) ans = mat_mul(ans, A); A = mat_mul(A, A); n >>= 1; } return ans.mapp[0][1];}int main() { int p = 1; while(scanf("%lld %lld", &m, &n) != EOF) { n++; mat base; base.mapp[0][0] = m; //构造初始矩阵 base.mapp[0][1] = base.mapp[1][1] = 1; base.mapp[1][0] = 0; printf("Case %d: %lld\n",p++ ,mat_pow(base) % mod); } return 0;}
逆元+快速幂:(详解)
分析:等比数列的前n项和公式:s = (q^n - 1) / (q - 1),现在求前n + 1项,由于数比较大对mod = 1e9 + 7取模,同余定理不适用除法,这个时候就需要求逆元,费马小定理+快速幂或者扩展欧几里得都可以(这里用的是费马小定理:a,p互质,则 a^(p - 1) % p = 1)。
设 A = q - 1,因为(A,mod) = 1(表示互质),A^(mod - 1) % mod = 1 ,所以,s = (q^n - 1) / (q - 1) = [ (q^n - 1) / (q - 1) ] * [ (q - 1)^(mod - 1) % mod] % mod = s = (q^n - 1) * (q - 1)^(mod - 2) % mod,这样用快速幂正常写就行了,特判一下1。
#include<bits/stdc++.h>using namespace std;typedef long long LL;const LL mod = 1000000007;LL q_mod(LL a, LL b) { LL ans = 1; while(b) { if(b&1) ans = ans * a % mod; a = a * a % mod; b >>= 1; } return ans;}int main(){// freopen("in.txt", "r", stdin);// freopen("o.txt", "w", stdout); LL a, b, x, n, k, cnt = 0; while(~scanf("%lld %lld", &k, &n)) { if(k == 1) { printf("Case %lld: %lld\n", ++cnt, n + 1); continue; } a = q_mod(k, n + 1) - 1; b = k - 1; x = q_mod(b, mod - 2); printf("Case %lld: %lld\n", ++cnt, a * x % mod); } return 0;}
- zzuli 2180 GJJ的日常之沉迷数学【矩阵快速幂 || 逆元】
- 【ZZULIOJ 2180】GJJ的日常之沉迷数学 【逆元 or 矩阵快速幂】
- zzuli 2180 GJJ的日常之沉迷数学(逆元)
- 2180: GJJ的日常之沉迷数学 (逆元)
- zzuli2180: GJJ的日常之沉迷数学
- GJJ的日常之沉迷数学
- GJJ的日常之沉迷数学
- Problem E: GJJ的日常之沉迷数学
- zzuli GJJ的日常之暴富梦
- 【zzuli 2175】(GJJ的日常之再游戏)
- 【zzuli 2181】(GJJ的日常之暴富梦)
- zzuli-2175: GJJ的日常之再游戏
- zzuli 2172 GJJ的日常之购物【dp+优先队列】
- ZZULIOJ【2181】GJJ的日常之暴富梦【思维】&&【数学】
- 2181: GJJ的日常之暴富梦(数学)
- 河南省多校连萌(四)【zzuli 2175 Problem A: GJJ的日常之再游戏】
- zzuli 2181 GJJ的日常之暴富梦 (思维,水题)
- 2175: GJJ的日常之再游戏
- How to write Lossfunction in PythonCaffe
- jQuery验证控件jquery.validate.js使用说明+中文API
- 根据经纬度查询附近企业 | SQL
- ZZULIOJ【2181】GJJ的日常之暴富梦【思维】&&【数学】
- HDU 2896病毒侵袭(AC自动机)
- zzuli 2180 GJJ的日常之沉迷数学【矩阵快速幂 || 逆元】
- vue自我总结
- 进程通信2——共享内存,信号量
- PHP基础教程-25 自动化编程
- HDU 6144 Arithmetic of Bomb(模拟)
- 搜索方式的优缺比较
- 数据结构之排序,归并求逆序数
- 根据经纬度算距离 | SQL
- 首页实现_旅游直播实现