1. 程式人生 > >34 除法分塊

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; }