• 湘潭 A simple problem


    A simple problem

    Accepted : 30   Submit : 303
    Time Limit : 15000 MS   Memory Limit : 655360 KB

    Problem Description

    There is a simple problem. Given a number N. you are going to calculate N%1+N%2+N%3+...+N%N.

    Input

    First line contains an integer T, there are T(1≤T≤50) cases. For each case T. The length N(1≤N≤1012).

    Output

    Output case number first, then the answer.

    Sample Input

    1
    5
    
    

    Sample Output

    Case 1: 4
    
    

    Source

    daizhenyang

     学习莫比乌斯反演的时候,用到了一些常数的优化。用这样的方法能够解决这一道题。

     当然找规律也是可以做的,其实都是一样的,只不过从一个归纳的角度去看这一道题。

    思路:先举个例子。

    15%1 = 0 等差数列!!只不过只有一个数而已么

    15%2 = 1 等差数列!!只不过只有一个数而已么

    15%3 = 2 等差数列!!只不过只有一个数而已么

    15%4 = 3   15%5=0 等差数列!!

    15%6 = 3   15%7=1 等差数列!!

    15%8 = 7    15%9=6   15%10=5.....  15%14=1   15%15=0 等差数列!!

    观察是可以得到的,其实这个是另一个的一种转化。就是/

    如果15/i == 15/(i+k) 那么这k个值都是相同。显然 。

    比如,拿最后一组来说15/8 == 15/(8+7),确实是。

    那么我们能用到莫比乌斯反演里讲的优化,求区间的上限就可以了。i - 区间上限,就是一个等差数列。

    上限的值为(n/(n/i)),解决。

    具体见代码:因为在求和过程中会溢出,所以我用java了。

     1// package ttMain;
     2 
     3 import java.math.BigInteger;
     4 import java.util.Scanner;
     5 
     6 public class Main{
     7 
     8     public static void main(String[] args) {
     9         Scanner cin = new Scanner(System.in);
    10         int T = cin.nextInt();
    11         for(int t=1;t<=T;t++)
    12         {
    13             long n = cin.nextInt();
    14             System.out.println("Case "+t+":"+" "+solve(n));
    15         }
    16     }
    17     
    18     private static BigInteger solve(long n) {
    19         
    20         BigInteger sum = BigInteger.ZERO;
    21         long d=0 ;
    22         /**
    23          * 看起来是一个for,10^12,其实不是的。是sqrt(n).
    24          * n/i == n/(k+i) 这里节省了很多的.
    25          */
    26         for(long i=1,la = 0;i<=n;i=la+1){
    27             la = n/(n/i);
    28             if(la==i){ //如果只有一个元素
    29                 sum = sum.add(BigInteger.valueOf(n%i));
    30                 continue;
    31             }
    32             //否则算出d
    33             d = n%(i+1) - n%i;
    34             sum = sum.add(GetSum(n%i,la-i+1,d));
    35         }
    36         return sum;
    37     }
    38 
    39     private static BigInteger GetSum(long a1, long n,long d) {
    40         /**
    41          * 求等差数列前n项和
    42          */
    43         BigInteger an = BigInteger.ZERO;
    44         an = BigInteger.valueOf(a1).
    45             add(BigInteger.valueOf(n-1).multiply(BigInteger.valueOf(d)));
    46         BigInteger sumn = BigInteger.valueOf(a1).add(an);
    47         sumn = sumn.multiply(BigInteger.valueOf(n)).divide(BigInteger.valueOf(2));
    48         return sumn;
    49     }
    50     
    51 }

    更为一般的情况:

    1257: [CQOI2007]余数之和sum

    Time Limit: 5 Sec  Memory Limit: 162 MB
    Submit: 1743  Solved: 810
    [Submit][Status]

    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

    Source

     
    源代码改一下就可以
     1 //package ttMain;
     2 
     3 import java.math.BigInteger;
     4 import java.util.Scanner;
     5 
     6 public class Main{
     7 
     8     public static void main(String[] args) {
     9         
    10         Scanner cin = new Scanner(System.in);
    11         long n = cin.nextLong();
    12         long k = cin.nextLong();
    13         BigInteger sum = BigInteger.ZERO;
    14         if(k<n){
    15             BigInteger tmpSum = BigInteger.valueOf(k);
    16             tmpSum = tmpSum.multiply(BigInteger.valueOf(n-k));
    17             sum = sum.add(tmpSum);
    18 //            System.out.println(tmpSum);
    19         }
    20         sum = sum.add(solve(k,n));
    21         System.out.println(sum);
    22     }
    23     
    24     private static BigInteger solve(long k,long n) {
    25         
    26         BigInteger sum = BigInteger.ZERO;
    27         long d=0 ;
    28         boolean flag = false;
    29         /**
    30          * 看起来是一个for,10^12,其实不是的。是sqrt(k).
    31          * k/i == k/(k+i) 这里节省了很多的.
    32          */
    33         for(long i=1,la = 0;i<=k;i=la+1){
    34             if(flag) break;
    35             la = k/(k/i);
    36             if(k>n && la>=n) {
    37                 la = n;
    38                 flag = true;
    39             }
    40             if(la==i){ //如果只有一个元素
    41                 sum = sum.add(BigInteger.valueOf(k%i));
    42                 continue;
    43             }
    44             //否则算出d
    45             d = k%(i+1) - k%i;
    46             sum = sum.add(GetSum(k%i,la-i+1,d));
    47         }
    48         return sum;
    49     }
    50 
    51     private static BigInteger GetSum(long a1, long n,long d) {
    52         /**
    53          * 求等差数列前n项和
    54          */
    55         BigInteger an = BigInteger.ZERO;
    56         an = BigInteger.valueOf(a1).
    57             add(BigInteger.valueOf(n-1).multiply(BigInteger.valueOf(d)));
    58         BigInteger sumn = BigInteger.valueOf(a1).add(an);
    59         sumn = sumn.multiply(BigInteger.valueOf(n)).divide(BigInteger.valueOf(2));
    60         return sumn;
    61     }
    62     
    63 }
  • 相关阅读:
    GOLANG之学习类库-mysql
    GOLANG学习之类库-goconfig
    PHP进程实现方式之死循环(一)
    PHPexcel之读取表格(三)
    PHPExcel之生成表格汇总列(二)
    GOLAND常用基本命令介绍
    PHPExcel之生成xlsx并下载(一)
    nginx之版本升级方法一
    php linux yaml 的安装和使用
    【Go语言学习笔记】Go的defer
  • 原文地址:https://www.cnblogs.com/tom987690183/p/3775784.html
Copyright © 2020-2023  润新知