BZOJ 1257 [CQOI2007]余数之和sum 题解

1257: [CQOI2007]余数之和sum

Time Limit: 5 Sec   Memory Limit: 162 MB
Submit: 1138   Solved: 509
[ 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

Source

数论

 
【分析】:
      求Σ(K%i),1≤i≤N
      K%i=K-(K/i)*i,对于i至K/(K/i)这一段K/i相同,可以一起算,可证总段数是sqrt(N)的。
      复杂度:O(Sqrt(N))
 
【代码】:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
#define MAXN 1000001
long long N,K,number[MAXN],tot=0;
long long ans=0;
int main()
{
      //freopen("input.in","r",stdin);
	  //freopen("output.out","w",stdout); 
	  scanf("%lld%lld",&N,&K);
	  for(int i=1;i<=(int)sqrt(K);i++)
	  {
            number[++tot]=i;
            if(K/i!=i)   number[++tot]=K/i;
      }
      sort(number+1,number+1+tot);
      long long last=(N>K?K:N);
      for(int i=1;i<=tot;i++)
      {
            if(number[tot-i]+1<=last)
            {
                  long long sigma_i=(number[tot-i]+1LL+last)*(last-number[tot-i])/2LL;
                  ans=ans-sigma_i*number[i];
                  last=number[tot-i];
            }
      }
      ans+=N*K;
      printf("%lld\n",ans);
	  //system("pause");
      return 0;
}

 
转载注明出处: http://blog.csdn.net/u011400953

你可能感兴趣的:(BZOJ 1257 [CQOI2007]余数之和sum 题解)