模运算与幂运算
来源:互联网 发布:dede源码素材资源网 编辑:程序博客网 时间:2024/05/06 13:08
模运算与幂运算
你需要花多少时间做下面这道题:
123456789 * 987654321 = ( )
A. 121932631112635266
B. 121932631112635267
C. 121932631112635268
C. 121932631112635269
既然是选择题,不必费力把答案完整地计算出来——4个选项的各位都不相同,因此只需要计算出答案的最后一位即可。不难看出:1 * 9 = 9。刚才的解题过程抽象出来就是下面的式子了:
123456789×987654321 mod 10 = (123456789 mod 10) × (987654321 mod 10) mod 10
其中a mod b表示a除以b的余数,C++语言是a % b。
不难得出下面的公式:
123456789 * 987654321 = ( )
A. 121932631112635266
B. 121932631112635267
C. 121932631112635268
C. 121932631112635269
既然是选择题,不必费力把答案完整地计算出来——4个选项的各位都不相同,因此只需要计算出答案的最后一位即可。不难看出:1 * 9 = 9。刚才的解题过程抽象出来就是下面的式子了:
123456789×987654321 mod 10 = (123456789 mod 10) × (987654321 mod 10) mod 10
其中a mod b表示a除以b的余数,C++语言是a % b。
不难得出下面的公式:
(a + b) mod p = ((a mod p) + (b mod p)) mod p
(a - b) mod p = ((a mod p) - (b mod p)) mod p
(a×b) mod p = ((a mod p) × (b mod p)) mod p
(ab) mod p = ((a mod p)b ) mod p
(a - b) mod p = ((a mod p) - (b mod p)) mod p
(a×b) mod p = ((a mod p) × (b mod p)) mod p
(ab) mod p = ((a mod p)b ) mod p
【程序1】大整数取模
输入正整数n和m,输出n mod m的值。n<=10100,m<=108。
【分析】利用上面的公式每步取模即可。例如n=123,m=7。则123 mod 7=((((1 mod 7)*10 + 2) mod 7)*10 + 3) mod 7 = 4:
【分析】利用上面的公式每步取模即可。例如n=123,m=7。则123 mod 7=((((1 mod 7)*10 + 2) mod 7)*10 + 3) mod 7 = 4:
#include <iostream>using namespace std;int main(){string n;int m;cin >> n >> m;int ans=0;for(int i=0;i<n.size();i++) ans = (int) (((long long )ans*10 + n[i]-48) % m);cout << ans;return 0;}
有一类常见的运算,就是求形如ab mod p的值,一般情况下,我们可以用幂的定义来作:通过乘法的倍乘来实现,需要做b次乘法和模运算。如果b较大时,这样的方法就不行了,下面的程序采用二分法进行优化。
【程序2】幂取模
输入正整数a、n和m,输出an mod m的值。a,n,m<=109。
【分析】本题采用二分法。本题的数据很大,必须时刻运用上面的公式:
a*b*c mod k = (((a mod k)*(b mod k) mod k) *(c mod k)) mod k
【分析】本题采用二分法。本题的数据很大,必须时刻运用上面的公式:
a*b*c mod k = (((a mod k)*(b mod k) mod k) *(c mod k)) mod k
#include <iostream>using namespace std;long long pow_mod(long long a, long long n, long long m){if(n==1) return a%m;long long x=pow_mod(a,n/2,m); if (n%2 == 1) return (((x % m)*(x % m)) % m *(a % m)) % m; else return ((x % m)*(x % m)) % m;}int main(){long long a,n,m;cin >> a >> n >> m;cout << pow_mod(a,n,m) << endl;return 0;}
上面的程序,对于b比较大时,还是无法通过的。那么我们可以采用二进制优化:
我们把b按二进制位展开,例如:
b=5,则5=20+22,得到a5=a20 + 22。也就是说,如果b可以表示成b=2b0+2b1+...+2bk的形式,那么ab可表示成:
ab = a2b0 + 2b1 + ... + 2bk = a2b0 × a2b1 × ... × a2bk
程序2“幂取模”的核心程序如下:
long long calc(int a, int b, int m){ //函数计算a^b mod m的值 int b1[32],r[32]; //b1存储b的二进制结果,r[i]表示2^i次方对m取模的结果 r[0]= a % m; //计算r[i] for (int i=1;i<32;++i) r[i]=(long)r[i-1]*r[i-1] % m; //r^(i+1) = (r^i) * (r^i) i=0; while (b){b1[i++] = b % 2;b>>=1; } for (int j=0,k=1; j<i; ++j) //计算乘方 if(b1[j]) k=k*r[j]%m; return k;}int main(){ scanf("%d%d%d",&a,&b,&m); printf("%u\n",calc(a,b,m));}
【程序3】高级模运算
人与人是不同的,有些人喜欢阅读杂志,有些人喜欢下棋,有的人喜欢麻烦的数字游戏。比如ESSE论坛的一次活动:
每个人选择两个数字ai和bi写在纸上,其他人不能看见。过了一段时间后,每个人说出自己纸上的数字,然后每个人的目标就是求出所有的 aibi的和模m的值,最先算出结果的,就是胜利者。
输入
输入包含Z组测试数据,第1行只包含数字Z。随后是测试数据:第1行是一个数字M(1<=M<=45 000)。第2行是数字H(1<=H<=45 000)表示参加游戏的人数。接下来H行,每行两个数ai和bi(1<=ai, bi<=231)。
输出
对于每组测试数据,输出以下表达式的值:
(a1b1 + a2b2 + ... + aHbH) mod M
输入样例
3
16
4
2 3
3 4
4 5
5 6
36123
1
2374859 3029382
17
1
318132
输入样例
2
13195
13
【分析】利用上面的模运算公式,表达式的任何中间结果都可以进行取模运算,使得中间结果不至于太大而溢出。本题采用二进制优化。
每个人选择两个数字ai和bi写在纸上,其他人不能看见。过了一段时间后,每个人说出自己纸上的数字,然后每个人的目标就是求出所有的 aibi的和模m的值,最先算出结果的,就是胜利者。
输入
输入包含Z组测试数据,第1行只包含数字Z。随后是测试数据:第1行是一个数字M(1<=M<=45 000)。第2行是数字H(1<=H<=45 000)表示参加游戏的人数。接下来H行,每行两个数ai和bi(1<=ai, bi<=231)。
输出
对于每组测试数据,输出以下表达式的值:
(a1b1 + a2b2 + ... + aHbH) mod M
输入样例
3
16
4
2 3
3 4
4 5
5 6
36123
1
2374859 3029382
17
1
318132
输入样例
2
13195
13
【分析】利用上面的模运算公式,表达式的任何中间结果都可以进行取模运算,使得中间结果不至于太大而溢出。本题采用二进制优化。
【程序4】模线性方程
输入正整数a,b,n,解方程 ax≡b(mod n)。 a,b,n≤10^9。
本题中出现了一个新记号:同余。a≡b(mod n)的含义是“a和b关于模n同余”,即 a mod n = b mod n。
不难看出:a≡b(mod n)的充要条件是: a-b是n的整数倍。
本题中出现了一个新记号:同余。a≡b(mod n)的含义是“a和b关于模n同余”,即 a mod n = b mod n。
不难看出:a≡b(mod n)的充要条件是: a-b是n的整数倍。
a≡b(mod n)的充要条件是 a-b是n的整数倍。
这样,原来的方程就可以理解成:ax-b是n的整数倍。设这个倍数为k,则ax-b=nk,移项得:ax-nk=b。这恰好就是前面介绍的不定方程,不再讨论,具体参看“3-1 最大公约数和最小公倍数”。
方程ax≡1(mod n)的解称为a关于模n的逆。当gcd(a,n)=1时,该方程有唯一解;否则无解。
0 1
- 模运算与幂运算
- [ 模运算 ] 与 [ 模取幂运算 ]
- [ 模运算 ] 与 [ 模取幂运算 ]
- [ 模运算 ] 与 [ 模取幂运算 ]
- 幂运算(与运算)
- 幂运算和模运算
- 用'与&'运算替代'取模%'运算
- 与运算代替模运算小记
- 整除运算与取模运算
- 移位运算与除法、取模运算
- &“与”运算
- 与运算
- Matlab运算符与运算
- 赋值运算与位运算
- 数值运算与运算符
- 算术运算与赋值运算
- 算术运算与赋值运算
- 模运算与同余
- 微信小程序 文字超过行后隐藏显示省略号
- 欢迎使用CSDN-markdown编辑器
- BZOJ 4033 树上染色 (题解)(树上动规)
- 从github上的优秀实例看MVP模式
- MySQL5.7版本的下载安装与配置
- 模运算与幂运算
- Ubuntu中root用户和user用户的相互切换
- hduoj-1501【dfs】【dp】
- 六天带你玩转Mysql笔记--第二天
- 欢迎使用CSDN-markdown编辑器
- 同余方程
- 在ARM开发板上实现LCD+USB键盘
- Android Hybrid 方案之 离线文件加载
- Spark Streaming 的玫瑰与刺