题意:
给出n, k,求
分析:
假设,则k mod (i+1) = k - (i+1)*p = k - i*p - p = k mod i - p
则对于某个区间,i∈[l, r],k/i的整数部分p相同,则其余数成等差数列,公差为-p
然后我想到了做莫比乌斯反演时候有个分块加速,在区间[i, n / (n / i)],n/i的整数部分相同,于是有了这份代码。
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL; int main()
{
LL n, k;
while(scanf("%lld%lld", &n, &k) == )
{
LL ans = ;
LL i, j, r = min(n, k);
for(i = ; i <= r; i = j + )
{
j = k / (k / i);
if(j > r) j = r; LL d = -k / i;
LL l = j - i + ;
LL a1 = k % i;
ans += (LL) (a1*l + l*(l-)/*d);
}
if(n > k)
ans += (LL) (n-k) * k; printf("%lld\n", ans);
} return ;
}
代码君
后来试了一下lrj的代码,比我的短还比我的快,给跪了
// UVa1363 Joseph's Problem
// Rujia Liu
#include<iostream>
#include<algorithm>
using namespace std; // 首项为a,公差为-d,除了首项之外还有n项
// 末项为a-n*d,平均数为(2*a-n*d)/2
long long sum(int a, int d, int n) {
return (long long)(*a-n*d)*(n+)/;
} int main() {
int n, k;
while(cin >> n >> k) {
int i = ;
long long ans = ;
while(i <= n) {
int q = k % i, p = k / i;
int cnt = n - i; // 最多还有n - i项
if(p > ) cnt = min(cnt, q / p);
ans += sum(q, p, cnt);
i += cnt + ;
}
cout << ans << "\n";
}
return ;
}
更快的代码君