• 洛谷 P2261 [CQOI2007]余数求和 题解


    一、题目:

    洛谷原题

    题目背景

    数学题,无背景

    题目描述

    给出正整数n和k,计算G(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值,其中k mod i表示k除以i的余数。例如G(10, 5)=5 mod 1 + 5 mod 2 + 5 mod 3 + 5 mod 4 + 5 mod 5 …… + 5 mod 10=0+1+2+1+0+5+5+5+5+5=29

    输入输出格式

    输入格式:

    两个整数n k

    输出格式:

    答案

    输入输出样例

    输入样例#1: 复制
    10 5
    输出样例#1: 复制
    29

    说明

    30%: n,k <= 1000

    60%: n,k <= 10^6

    100% n,k <= 10^9

    二、思路

    数论分块题模板题。

    (ans)

    (=sum_{i=1}^n k mod i)

    (=sum_{i=1}^n k-i imes lfloor frac{k}{i} floor)

    我们注意到(lfloor frac{k}{i} floor)在i的一定范围内是相等的,所以我们可以不断算出这个范围,然后一次性计算即可。由于(lfloor frac{k}{i} floor)的不同取值大概有(sqrt n)个,所以时间复杂度为(O(sqrt n))

    三、代码:

    /*
     * @Author: 岸芷汀兰
     * @Date: 2018-11-05 22:25:21
     * @LastEditors: 岸芷汀兰
     * @LastEditTime: 2018-11-05 23:14:56
     * @Description: P2261 of luogu
     */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    #define LL long long
    #define mem(s,v) memset(s,v,sizeof(s))
    
    using namespace std;
    template<class Type>
    inline Type read(void){
        Type x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return f*x;
    }
    
    LL n,k,ans;
    
    LL Sum(LL l,LL r){
        return (l+r)*(r-l+1)/2;
    }
    
    int main(){
        n=read<LL>();k=read<LL>();
        LL l=1;
        ans=n*k;
        while(l<=n){
            LL shang=k/l,r;
            if(shang)r=min(k/shang,n);
            else r=n;
            LL sum=shang*Sum(l,r);
            ans-=sum;
            l=r+1;
        }
        cout<<ans<<endl;
        return 0;
    }
    
  • 相关阅读:
    4.26上午
    4.25下午
    4.19上午
    4.18上午
    7.26
    7.25
    7.21-7.22
    7.22
    7.21
    7.11-7.15
  • 原文地址:https://www.cnblogs.com/little-aztl/p/9914628.html
Copyright © 2020-2023  润新知