zoukankan      html  css  js  c++  java
  • Codeforces

    题目链接:http://codeforces.com/contest/616/problem/E

    题目大意:给定整数n,m(1≤n,m≤1013), 求(n mod 1 + n mod 2 + ... + n mod m)的值(mod Pt = 1e9 + 7)。

    思路:这题一看是看觉得题意简洁,通过人数不多一定是一道用到各种定理的碉堡数论题。后来仔细想了一下发现是乱搞…

    首先通过观察数据范围,结合数论题的复杂度传统考虑O(√n)算法。

    把n拆解,可以任意写成很多种n = px + r 的形式,而p, x中必有一个≤√n,首先对于[1,√n]的x暴力处理n % x,而当x > √n的时候,就出现了一个[1, √n]的p,对应一段连续的x的情况,同样r也是对应的。如果能够快速批处理出这些r的和,那么就能通过1 - √n枚举p来搞定x∈[√n, +∞]的情况。通过观察,对于任何一个p对应的连续的x区间,r都成首项为n - (n / p) * p, 公差为p,项数为n / p - n / (p + 1)的等差数列前n项和,因此带入公式可O(1)得解。 先枚举p去做代码比较好些,直到n / p < √n,把成块的x处理结束,剩下谁就直接从1到那个值暴力枚举计算比较容易写。

    当m > n的时候把m变成n,答案初始为n * (m - n) 即可。值得注意的是m < n的时候,要注意从p等于多少开始能覆盖到m,那个边界的x区间中,r的首项为n % m。

    题目要求% Pt, 这一点卡的很严,注意n % m之后还要再 % Pt,而且中间计算的过程中每一步运算都要%,防止爆long long。

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 using namespace std;
     7 typedef long long LL;
     8 
     9 const LL Pt = 1e9 + 7;
    10 LL n, m, d1, d2, a, k, ans, pos, ans1;
    11 
    12 int main()
    13 {
    14     scanf("%I64d%I64d", &n, &m);
    15     if (m > n) ans = ((n % Pt) * ((m - n) % Pt)) % Pt, m = n;
    16     bool flag = false;
    17     for (LL i = 2; i <= n; i++)
    18     {
    19         d1 = n / i; d2 = n / (i - 1);
    20         if (d1 < m && !flag) 
    21         {
    22             flag = true;
    23             a = (n % m) % Pt;
    24             k = (m - d1) % Pt;
    25             a = ((a * k) % Pt + (((k * (k - 1) / 2) % Pt) * (i - 1)) % Pt) % Pt;
    26             ans = (ans + a) % Pt;
    27             continue;
    28         }
    29         if (flag)
    30         {
    31             a = (n - d2 * (i - 1)) % Pt;
    32             k = (d2 - d1) % Pt;
    33             a = ((a * k) % Pt + (((k * (k - 1) / 2) % Pt) * (i - 1)) % Pt) % Pt;
    34             ans = (ans + a) % Pt;
    35         }
    36         if (d1 <= sqrt(n)) {pos = d1; break;}
    37     }
    38     for (LL i = 1; i <= min(pos, m); i++) ans = (ans + n % i) % Pt;
    39     printf("%I64d
    ", ans);
    40 }
    View Code
  • 相关阅读:
    LeetCode 404. 左叶子之和
    三年了
    LeetCode 543. 二叉树的直径
    求结点在二叉排序树中层次的算法
    LeetCode 98. 验证二叉搜索树
    LeetCode 236. 二叉树的最近公共祖先
    LeetCode 129. 求根到叶子节点数字之和
    LeetCode 113. 路径总和 II
    LeetCode 107. 二叉树的层次遍历 II
    LeetCode 144. 二叉树的前序遍历 (非递归)
  • 原文地址:https://www.cnblogs.com/ChopsticksAN/p/5148646.html
Copyright © 2011-2022 走看看