34 除法分块

Problem C — limit 1 second

Fear Factoring

The Slivians are afraid of factoring; it’s just, well, difficult.

Really, they don’t even care about the factors themselves, just how much they sum to.

We can define

F(n) as the sum of all of the factors ofn; soF(6) = 12 andF(12) = 28. Your taskis, given two integersaandbwitha≤b, to calculateS=∑a≤n≤bF(n).InputThe input consists of a single line containing space-separated integersaandb(1≤a≤b≤1012;b−a≤106).OutputPrintSon a single line.

整数除法分块的方法主要解决的问题是除法,因子问题,时间复杂度是根号的,主要利用的就是在某一个数的范围内部,有多少个数字是1,2,3,4,5,6,的倍数,并且这里的多少个有很多时候是相同的就是从某一个数字开始这个范围内它的倍数个数不在和前面的数字的倍数个数相同的话,那么从这个数字开始到n/(n/i)这个数字的倍数的个数在这个范围内都是这个数,这样的话我们就就可以很快的求出(根号)与除法有关的相关数据;

rep(i,1,20){
      printf("%lld %lld %lld\n",i,20/i,(20/(20/i)));
    }

在这里的话我们就是有20是这里的范围,从上面的数据我们可以分析出来就是对于i,我们有n/i个数字是他的倍数

我们拿7来看有2(20/7)(n/i)个数字是它的倍数7,14,正好我们也发现了在20范围内有两个数字是它倍数的数字还有8,

9,10(20/(20/10))(n/(n/i))正好是跟前面的个数不同的话我们就有从这个数字开始一直到了n/n/i都会有n/i个数字是i的倍数

#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int Max = 1e3+10;

#define rep(i,s,n) for(ll i=s;i<=n;i++)
#define per(i,n,s) for(ll i=n;i>=s;i--)

ll solve(ll n){
   ll ans=0,i=1,ans1;
   //ll num=0;
   while(i<=n){
     ans1=(n/(n/i)-i+1);
     ans1*=(n/(n/i)+i);
     ans1/=2;
     ans1*=(n/i);
     ans+=ans1;
     i=n/(n/i)+1;
     //num++;
   }
   //printf("%llu\n",num);
   return ans;
}
int main(){
//    rep(i,1,20){
//      printf("%lld %lld %lld\n",i,20/i,(20/(20/i)));
//    }
    ll a,b;
    scanf("%llu %llu",&a,&b);
    printf("%llu\n",solve(b)-solve(a-1));
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39792342/article/details/82780855
34