Description
F(n) = (n % 1) + (n % 2) + (n % 3) + ...... (n % n)。其中%表示Mod,也就是余数。
例如F(6) = 6 % 1 + 6 % 2 + 6 % 3 + 6 % 4 + 6 % 5 + 6 % 6 = 0 + 0 + 0 + 2 + 1 + 0 = 3。
给出n,计算F(n)。
Input
输入1个数N(2 <= N <= 10^12)。
Output
输出F(n)。
Sample Input
6
Sample Output
3
这是51NOD上的一道题,由于提交不了,所以搞到我们学校的OJ提交了。
这个题目n达10^12这么大,自然不可能走一遍。
然后由于n%i = n-[n/i]*i
所以sum(n%i) = sum(n-[n/i]*i) = n*n - sum([n/i]*i)。
考虑到取整那部分,当i在连续的一段区间内可能值会不变。
=>[n/i] = [n/j] => j = n/(n/i)这里的除法为取下整。
于是便可以考虑分组运算了。
由于数据很大,用了C++高精度。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <map> #include <queue> #include <string> #define LL long long using namespace std; const int UNIT = 10; struct Bignum { int val[30]; int len; Bignum() { memset(val, 0, sizeof(val)); len = 1; } Bignum operator=(const LL &a) { LL t, p = a; len = 0; while (p >= UNIT) { t = p - (p/UNIT)*UNIT; p = p / UNIT; val[len++] = t; } val[len++] = p; return *this; } Bignum operator+(const Bignum &a) const { Bignum x = a; int L; L = a.len > len ? a.len : len; for (int i = 0; i < L; ++i) { x.val[i] += val[i]; if (x.val[i] >= UNIT) { x.val[i+1]++; x.val[i] -= UNIT; } } if (x.val[L] != 0) x.len = L+1; else x.len = L; return x; } Bignum operator-(const Bignum &a) const { bool flag; Bignum x1, x2; if (*this > a) { x1 = *this; x2 = a; flag = 0; } else { x1 = a; x2 = *this; flag = 1; } int j, L = x1.len; for (int i = 0; i < L; ++i) { if (x1.val[i] < x2.val[i]) { j = i+1; while (x1.val[j] == 0) j++; x1.val[j--]--; while (j > i) x1.val[j--] += UNIT-1; x1.val[i] += UNIT-x2.val[i]; } else x1.val[i] -= x2.val[i]; } while (x1.val[x1.len-1] == 0 && x1.len > 1) x1.len--; if (flag) x1.val[x1.len-1] = -x1.val[x1.len-1]; return x1; } Bignum operator*(const Bignum &a) const { Bignum x; int i, j, up; int x1, x2; for (i = 0; i < len; i++) { up = 0; for (j = 0; j < a.len; j++) { x1 = val[i]*a.val[j] + x.val[i+j] + up; if (x1 >= UNIT) { x2 = x1 - x1/UNIT*UNIT; up = x1 / UNIT; x.val[i+j] = x2; } else { up = 0; x.val[i+j] = x1; } } if (up != 0) x.val[i+j] = up; } x.len = i + j; while (x.val[x.len-1] == 0 && x.len > 1) x.len--; return x; } Bignum operator/(const int &a) const { Bignum x; int down = 0; for (int i = len-1; i >= 0; --i) { x.val[i] = (val[i]+down*UNIT) / a; down = val[i] + down*UNIT - x.val[i]*a; } x.len = len; while (x.val[x.len-1] == 0 && x.len > 1) x.len--; return x; } LL operator%(const LL &a) const { LL x = 0; for (int i = len-1; i >= 0; --i) x = ((x*UNIT)%a+val[i]) % a; return x; } bool operator>(const Bignum &a) const { int now; if (len > a.len) return true; else if (len == a.len) { now = len - 1; while (val[now] == a.val[now] && now >= 0) now--; if(now >= 0 && val[now] > a.val[now]) return true; else return false; } else return false; } }ans, tmp, ttmp; LL n; void work() { ans = n; ans = ans*ans; LL j; for (LL i = 1; i <= n; i++) { j = n/(n/i); tmp = i+j; ttmp = j-i+1; tmp = tmp*ttmp; tmp = tmp/2; ttmp = n/i; tmp = tmp*ttmp; ans = ans-tmp; i = j; } } void output() { for (int i = ans.len-1; i >= 0; --i) printf("%d", ans.val[i]); printf("\n"); } int main() { //freopen("test.in", "r", stdin); while (scanf("%lld", &n) != EOF) { work(); output(); } return 0; }
时间: 2024-10-11 16:25:07