bzoj 1257: [CQOI2007]余数之和sum

1257: [CQOI2007]余数之和sum

Time Limit: 5 Sec   Memory Limit: 162 MB
Submit: 3145   Solved: 1450
[ Submit][ Status][ Discuss]

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

题解:自己想了好久,稍微有点思路,单一直WA,最后才知道,没考虑好,直接暴力不行,我们发现一个数在除于一个连续的数列时(取整),总会有一些商是相等的,而且进行取余时得到的结果是等差数列!例如:10/4,10/5;11/4,11/5;

这样我们可以按照商对连续数列的进行分组(商相同的在一个组里面),

根据:等差数列的性质  Sn=n(a1+an)/2;进行运算!

具体看 AC code 

#include<stdio.h>
#define ll long long 
ll min(ll a,ll b)
{
	return  a>b?b:a;
 } 
int main()
{
	ll  n,k;
	while(scanf("%lld%lld",&n,&k)!=EOF)
	{
	ll sum=0;
	ll now=2,left,right,xnum,sumlr,t1,extranum,extrasumlr,extra;
			while(now<=min(n,k))
		    {
		    	left=now;//该等差数列的最小一项值 a1; 
		    	t1=k/now;
		    	right=k/t1; //该等差数列的最大一项值 an;
		    	sumlr=k%left+k%right; //a1+an 
		    	xnum=right-left+1;//n项 
		    	sum+=(sumlr*xnum)/2;//Sn=n(a1+an)/2
		    	if(right>n)//当超出规定的界限时,进行超出数列的减 
		    	{
		    		extrasumlr=k%(n+1)+k%right;//从超出的第一项An+1到最大的项 
		    		extranum=right-n;//超出的项数 
		    		extra=(extrasumlr*extranum)/2;//Sn=n(a1+an)/2 
		    		sum-=extra;
				}
				now=right+1;
			}
		if(n>k)
		sum+=(n-k)*k;
		printf("%lld\n",sum);
	}
	return  0;
 } 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值