C++ 模量的重复循环
是否有一种有效的方法来查找1111..nmod M的值?C++ 模量的重复循环,c++,algorithm,discrete-mathematics,modular-arithmetic,C++,Algorithm,Discrete Mathematics,Modular Arithmetic,是否有一种有效的方法来查找1111..nmod M的值? 人们总是可以使用重复的平方运算来找到100mod M+101mod M+102mod M+103mod M+…10nmod M 有比这更快的方法吗?如果10是幂零的(如果M=2^a*5^b),或者在某个点开始循环,那么10的幂最终将达到0。(实际上,0,0,0…也是一个循环。)循环的长度可以与M-1一样大。因此,计算幂直到观察到重复值,并使用简单代数收集观察到的不同幂的项 我相信这将复杂性从O(n)降低到O(M),这显然是对大n的改进。您
人们总是可以使用重复的平方运算来找到
100mod M+101mod M+102mod M+103mod M+…10nmod M
有比这更快的方法吗?如果10是幂零的(如果M=2^a*5^b),或者在某个点开始循环,那么10的幂最终将达到0。(实际上,0,0,0…也是一个循环。)循环的长度可以与M-1一样大。因此,计算幂直到观察到重复值,并使用简单代数收集观察到的不同幂的项
我相信这将复杂性从O(n)降低到O(M),这显然是对大n的改进。您可以使用类似于平方求幂的算法来解决这个问题 首先,如果您有偶数个1,您可以看到:
11111111 = 1111 * 10001
n ones n/2 ones (10^(n/2) + 1)
这是一个数的两倍。而且
1111111 = 111111 * 10 + 1
n ones n-1 ones
将这些观察结果形式化,为了方便起见,将n个111…1的数字命名为J(n):
- 如果n是偶数,则J(n)=(10^(n/2)+1)J(n/2)
- 如果n是奇数,则J(n)=10*J(n-1)+1
M
(你需要M^2来适应你的类型),你必须使用比int
更长的类型
#包括
//将a计算为n模m的幂。
内部功率模块(内部a、内部n、内部m){
如果(n==0){返回1;}
如果(n==1){返回a;}
如果(n%2==0){
int k=功率模m(a,n/2,m);
返回(k*k)%m;
}
返回(功率模式m(a,n-1,m)*a)%m;
}
//计算J(n)模m
int j_mod_m(int n,int m){
如果(n==1){
返回1;
}
如果(n%2==0){
返回(j_mod m(n/2,m)*(1+pow_mod m(10,n/2,m)))%m;
}
返回(j_mod_m(n-1,m)*10+1)%m;
}
int main(int argc,字符**argv){
对于(int i=1;i<1000;i++){
printf(“%d:%d\n”,i,j_mod_m(i,12345));
}
返回0;
}
Euler的Totient函数为循环时间设定了上限。因此,你可以运行它,让你知道在第一时间找到周期是否值得。是否有一个公式来计算周期的长度?@user3318603简短回答,不是真的。这是现代密码学所依赖的无法解决的问题之一。如果(n==1){return a;}if(n==1){return a mod m;}inpow_mod m
,不应该是。我不认为编写的代码会产生错误的结果,除非有溢出,但是对于您的代码版本,产生溢出的值的范围更小。
#include <stdio.h>
// Computes a to the power of n modulo m.
int pow_mod_m(int a, int n, int m) {
if (n == 0) { return 1; }
if (n == 1) { return a; }
if (n % 2 == 0) {
int k = pow_mod_m(a, n/2, m);
return (k * k) % m;
}
return (pow_mod_m(a, n-1, m) * a) % m;
}
// Computes J(n) modulo m
int j_mod_m(int n, int m) {
if (n == 1) {
return 1;
}
if (n % 2 == 0) {
return (j_mod_m(n/2, m) * (1 + pow_mod_m(10, n/2, m))) % m;
}
return (j_mod_m(n-1, m) * 10 + 1) % m;
}
int main(int argc, char**argv) {
for (int i = 1; i < 1000; i++) {
printf("%d: %d\n", i, j_mod_m(i, 12345));
}
return 0;
}