Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 模量的重复循环_C++_Algorithm_Discrete Mathematics_Modular Arithmetic - Fatal编程技术网

C++ 模量的重复循环

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的改进。您

是否有一种有效的方法来查找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的改进。

您可以使用类似于平方求幂的算法来解决这个问题

首先,如果您有偶数个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
您可以使用这些循环(加上通过平方计算10^(n/2))模M的实际求幂实现,以O(log(n)^2)时间计算结果

下面是一些实现此功能的C代码。如果你想要一个大的
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;}in
pow_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;
}