BZOJ-1257-[CQOI2007]余数之和sum
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
题解
这道题看了我挺久的
我们可以把k%x转化成k-[k/x]*x
不考虑上限为n的情况 我们假设[k/x]=a(a>0),那么x的区间的head就是[k/(a+1)]+1,tail就是[k/a]
这样我们可以通过求取这一段区间的值(就是等差数列),求出这段区间的k%x的值
a每次改成[k/(head-1)]
head和tail随之改变
这样依次做下去直到head变为1
这样时间复杂度就是a的个数 O(√k)
但是如果x>k呢 实际上x>k的情况只可能在n>k的时候出现
a开始的值为[k/n]=0,head和tail刚开始的值分别[k/(0+1)]+1和n,发现是正确的
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 ll n,k,ans,sum,h,t,num,cnt; 5 int main(){ 6 scanf("%lld%lld",&n,&k); 7 cnt=k/n; 8 t=n; 9 h=k/(cnt+1)+1; 10 ans+=k*(t-h+1)-cnt*(t-h+1)*(t+h)/2; 11 while (h>1){ 12 cnt=k/(h-1); 13 t=k/cnt; 14 h=k/(cnt+1)+1; 15 ans+=k*(t-h+1)-cnt*(t-h+1)*(t+h)/2; 16 } 17 printf("%lld\n",ans); 18 return 0; 19 }