• 【BZOJ1257】余数之和(数论分块,暴力)


    【BZOJ1257】余数之和(数论分块,暴力)

    题解

    Description

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

    Input

    输入仅一行,包含两个整数n, k。

    Output

    输出仅一行,即j(n, k)。

    Sample Input

    5 3

    Sample Output

    7

    HINT

    50%的数据满足:1<=n, k<=1000 100%的数据满足:1<=n ,k<=10^9

    题解

    很Interesting的一道题目
    所求为

    [sum_{i=1}^n{k} \% {i} ]

    而这个式子可以再改一下

    [sum_{i=1}^nk-i*(k div i) ]

    其中(div)是整除
    前面的(n*k)直接先算出来
    后面的东西,很容易观察到,(i)是单增的
    (k/i)在一段范围内是不会变化的
    因此,每次求出这一段范围,然后直接计算等差数列即可

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    inline int read()
    {
    	int x=0,t=1;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return x*t;
    }
    long long ans,n,k;
    int main()
    {
    	n=read();k=read();
    	ans=n*k;
    	for(long long l=1,r=0;l<=n;l=r+1)
    	{
    		if(k/l)r=min(n,k/(k/l));
    		else r=n;
    		ans-=(k/l)*(r-l+1)*(l+r)>>1;
    	}
    	
    	printf("%lld
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    修改大表结构注意事项
    短信猫 Mysql ODBC问题
    各互联网公司UDE分享
    MySQL 取分类后的前n条
    批处理当前日期
    Fixed Event Scheduler No data zero rows fetched, selected, or processed
    数据库设计注意事项
    本月,下一月, 上一月 的 1号, 最后一号
    自动化测试编程语言的选择
    QTP描述编程中使用正则表达式
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8067594.html
Copyright © 2020-2023  润新知