Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.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
Algorithm 在一个范围内查找mod操作的总和_Algorithm_Math - Fatal编程技术网

Algorithm 在一个范围内查找mod操作的总和

Algorithm 在一个范围内查找mod操作的总和,algorithm,math,Algorithm,Math,如果我们有两个数字,比如说a和b,那么我们如何找到b%i的和的值,其中i的范围是1到a? 一种方法是迭代从1到a的所有值,但是有没有有效的方法? (比O(n)好?) 例如:如果a=4,b=5,则要求ans=5%1+5%2+5%3+5%4=4 谢谢。对于i>b,我们有b%i==b,因此可以在恒定时间内轻松计算出部分总和((a-b)*b,如果a>=b,则0) 对于i的部分,仅在a b so\sum_{i=b}^a=a(a-1)/2-b(b-1)/2的情况下找到一个解就足够了。 #include &l

如果我们有两个数字,比如说
a和b
,那么我们如何找到b%i的
和的值,其中i的范围是1到a
? 一种方法是迭代从1到a的所有值,但是有没有有效的方法? (比O(n)好?) 例如:如果a=4,b=5,则要求ans=5%1+5%2+5%3+5%4=4
谢谢。

对于
i>b
,我们有
b%i==b
,因此可以在恒定时间内轻松计算出部分总和(
(a-b)*b
,如果
a>=b
,则0)


对于
i的部分,仅在a b so\sum_{i=b}^a=a(a-1)/2-b(b-1)/2的情况下找到一个解就足够了。
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

unsigned long long usqrt(unsigned long long n);
unsigned long long modSum(unsigned long long a, unsigned long long b);

int main(int argc, char *argv[]){
    unsigned long long a, b;
    b = (argc > 1) ? strtoull(argv[argc-1],NULL,0) : 10000;
    a = (argc > 2) ? strtoull(argv[1],NULL,0) : b;
    printf("Sum of moduli %llu %% i for 1 <= i <= %llu: %llu\n",b,a,modSum(a,b));
    return EXIT_SUCCESS;
}

unsigned long long usqrt(unsigned long long n){
    unsigned long long r = (unsigned long long)sqrt(n);
    while(r*r > n) --r;
    while(r*(r+2) < n) ++r;
    return r;
}

unsigned long long modSum(unsigned long long a, unsigned long long b){
    if (a < 2 || b == 0){
        return 0;
    }
    unsigned long long sum = 0, i, l, u, r = usqrt(b);
    if (b < a){
        sum += (a-b)*b;
    }
    u = (a < r) ? a : r;
    for(i = 2; i <= u; ++i){
        sum += b%i;
    }
    if (r < a){
        u = (a < b) ? a : (b-1);
        i = b/u;
        l = b/(i+1);
        do{
            sum += (u-l)*b;
            sum -= i*(u-l)*(u+l+1)/2;
            ++i;
            u = l;
            l = b/(i+1);
        }while(u > r);
    }
    return sum;
}