zoukankan      html  css  js  c++  java
  • [CQOI2007]余数求和

    [CQOI2007]余数求和

    题目链接

    题意简述:

      给出n,k求k%1~n每一个数的和

    解题思路

      1.式子变形

      首先将原始式子变形成为nk-(k/1*1+k/2*2...k/n*n),此处的除法都是向下取整,也就是说不可以使用运算律了。

      2.区间思想

      那么我们通过简化式子,得到了一个不能用运算律的式子。此时我们发现不能暴力去算他。于是尝试着找了一会规律,可得到一个表格。(以100为例)

     (相同的用颜色标记出来)

    如果说颜色是区间的话。那么知道左端点就可以知道右端点

    记左端点为x,右端点为y.   y=k/(k/i),注意此处k/i向下取整。

    又由于区间与区间是相连的,所以说下一个区间的左端点为这一个区间的右端点加一

    并且第一个区间的左端点为1.由此可以计算出所有的区间。

    3.利用区间思想解题&额外补充

      1)解题:

          将区间思想与式子结合起来。将k/1*1+k/2*2...k/n*n按照区间分开来计算。知道k/i的定值,提取一个k/i的公因数,剩下的x,x+1,x+2...求和。

      2)额外补充:

           右端点取出来可能大于n,要处理一下。

           当n>k的时候,会出现k/i=0的情况,先把后面的累积到答案中,然后切换成n=k的子任务。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    ll n,k,ans;
    int main(){
        cin>>n>>k;
        if(n>k){
            ans=(n-k)*k;
            n=k;
        }
        ll z=1,y=1;
        while(z<=n){
            int x=k/z,num;
            y=min(n,k/x);
            num=y-z+1;
            ans+=num*k-x*((z+y)*num/2);
            z=y+1;
        }
        cout<<ans;
        return 0;
    }
    View Code
  • 相关阅读:
    类变量、绑定方法、静态方法和类方法
    面向对象练习及补充
    2、error:file /usr/bin/ ** mysql-client-5.6.39-1.el7.x86_64
    15、Linux 磁盘映射DM
    14、echo “$JAVA_HOME/bin” >>/etc/profile 转义
    typora文件导出word
    1、Rocketmq centos7下安装及使用
    13、hostname及hostnamectl区别
    1、MySql集群
    Hadoop安装
  • 原文地址:https://www.cnblogs.com/clockwhite/p/12038597.html
Copyright © 2011-2022 走看看