题目大意:给定n和k,求 ∑1<=i<=n(k mod i)
题目分析:n和k很大,直接算会TLE,但是可以先打表找规律。(点击可见数学推导)
随便找几组数据可以发现下面的规律
1)如果k/i的值相等,那么kmodi的值成等差数列(连续的)
2)如果k比n大,那么k/i的值随i的值增大而减小
3)如果k比n小,那么kmodi 大于k,当i大于k时
可见,主要解决的问题就是1),找到连续的成等差数列的区间。因为有规律3),所以不妨从后面往前找。如果发现了前面的规律,那么就会发现下 面的规律:
4) 从后往前找,如果从j开始出现等差数列(j为等差数列第一项),那么该等差数列的最后一项为k/(k/j+1)+1
但是等差数列不一定出现,如果k/(k/j+1) >= j。
代码:
#include <stdio.h>
long long solve(int n,int k)
{
long long ans = 0;
if(n > k)
{
ans += (long long)(n-k) * k;
n = k;
}
int div = k/n;
while(n > 1)
{
int id = k/(div+1);
if(id >= n)
{
ans += k % n;
n--;
div = k/n;
continue;
}
int s = k%n;
int e = k%(id+1);
ans += (((long long )(s+e)*(n-id))>>1);
n = id;
div++;
}
return ans;
}
int main()
{
int n,k;
while(scanf("%d%d",&n,&k) != EOF) printf("%lld\n",solve(n,k));
return 0;
}