码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 1257: [CQOI2007]余数之和sum 数学 && 枚举

时间:2014-09-05 18:05:11      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   os   io   for   数据   

 1257: [CQOI2007]余数之和sum

Time Limit: 5 Sec  Memory Limit: 162 MB
Submit: 1779  Solved: 823
[Submit][Status]

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

 

  segma(n%x)=segma(n-n/x*x)=n*k-segma(n/x*x)

  很容易发现,当我们枚举x计算n/x时,当x较大时,大量x对应相同的n/x,则我们可以枚举n/x,从1至sqrt(n),只枚举一半是因为当n/x较大时,很多n/x并没有相应x对应,所以由于之前枚举n/x处理了区间[x0,k]的x,那么我们就可以枚举[1,x0-1]中的x,两种方法即可在sqrt(n)时间内解决问题。

 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define MAXN 10000
typedef long long qword;
int main()
{
        freopen("input.txt","r",stdin);
        int n,m;
        scanf("%d%d",&m,&n);
        int i,j,k;
        qword x0,x1;
        qword ans=(qword)n*m;
        int l=floor(sqrt(n));
        for (i=0;i<=l;i++)
        {
                //n%x=n-n/x*x
                //n/x=i
                if (i==0)
                        x1=m;
                else 
                        x1=min(m,n/i);
                x0=n/(i+1)+1;
                if (x0>x1)
                        continue;
                ans-=(qword)i*(x0+x1)*(x1-x0+1)/2;
        }
        for (i=1;i<min(m+1,(int)x0);i++)
        {
                ans-=n/i*i;
        }
        printf("%lld\n",ans);
}

 

bzoj 1257: [CQOI2007]余数之和sum 数学 && 枚举

标签:des   style   blog   http   color   os   io   for   数据   

原文地址:http://www.cnblogs.com/mhy12345/p/3958437.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!