【除法分块】

T1:题目传送门

T1题意 : 定义f(n)为n 的因子和,给你l,r,求 f ( l ) + f ( l + 1 ) + … + f ( r )

思路: 首先,我们可以定义g(n) 为 f (n) 的前缀和,那么所求式子即 g( r )-g(l-1),对于一个g(n),我们可以得到式子 g(n) = n / 1 * 1 + n / 2 * 2 + n / 3 * 3 + …+n / n *n, (每个因子出现的次数乘因子贡献。)

我们可以把出现次数相同的因子,分为一个块,每个块有一个左边界一个右边界,我们可以知道,当前块的左边界等于上一个块的右边界+1,右边界等于上限(n)/当前块的次数,而当前块的次数就是上限(n)/左边界,即 r=n/(n/r)。

最后对每一个块进行等差数列求和就行了。

代码:

#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
#define endl '\n'
#define null NULL
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define pii pair<int,int>
#define ull unsigned long long
#define pdd pair<double,double>
#define lowbit(x) x&-x
#define all(x) x.begin(),x.end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read()
{
    
    
    int x=0,f=1;
    char ch=gc();
    while(ch<'0'||ch>'9')
    {
    
    
        if(ch=='-')
            f=-1;
        ch=gc();
    }
    while(ch>='0'&&ch<='9')
    {
    
    
        x=x*10+ch-'0';
        ch=gc();
    }
    return x*f;
}
using namespace std;
const int N=3e5+1000;
const int inf=0x3f3f3f3f;
const int mod=998244353;
const double eps=1e-6;
const double PI=acos(-1);

ull solve(ull n)
{
    
    
    ull sum=0,l,r;
    for(l=1;l<=n;l=r+1)
    {
    
    
        r=n/(n/l);
        sum+=(n/l)*(r-l+1)*(r+l)/2;
    }
    return sum;
}
signed main()
{
    
    
	ull l,r;
	cin>>l>>r;
	cout<<solve(r)-solve(l-1)<<endl;
}

T2:题目传送门

题意: 给你n,k,让你求k%1+k%2+ … +k%n。

思路: 我们可以分两种情况讨论。

情况1 :n>=k,此时我们可以将式子转化成 k%1+k%2 + … +k%k +k * (n-k) ,然后,k%i = k -k / i * i,所以式子转化成 k * k - (k / 1 * 1 + k / 2 * 2 + … + k / k * k) +k * (n-k) ,然后直接套取板子。

情况2 :n<k ,此时我们仍然可以套取板子,只是在计算时,当一个块的右端点超过了n,要把它置为n,否则会多算,同样,这时候我们也不需要考虑第一种情况中的 k*(n-k)。

代码:

#include<bits/stdc++.h>
#define endl '\n'
#define null NULL
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define pii pair<int,int>
#define ull unsigned long long
#define pdd pair<double,double>
#define lowbit(x) x&-x
#define all(x) x.begin(),x.end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read()
{
    
    
    int x=0,f=1;
    char ch=gc();
    while(ch<'0'||ch>'9')
    {
    
    
        if(ch=='-')
            f=-1;
        ch=gc();
    }
    while(ch>='0'&&ch<='9')
    {
    
    
        x=x*10+ch-'0';
        ch=gc();
    }
    return x*f;
}
using namespace std;
const int N=3e5+1000;
const int inf=0x3f3f3f3f;
const int mod=998244353;
const double eps=1e-6;
const double PI=acos(-1);

ull solve(ull n,ull k)
{
    
    
    ull sum=0,l,r;
    for(l=1;l<=k;l=r+1)
    {
    
    
        r=k/(k/l);
        if(r>n)
            r=n;
        sum+=(l+r)*(r-l+1)*(k/l)/2;
        if(r==n)
            break;
    }
    return sum;
}
signed main()
{
    
    
    ull n,k;
    cin>>n>>k;
    if(n>k)
        cout<<k*k-solve(n,k)+k*(n-k)<<endl;
    else
        cout<<n*k-solve(n,k)<<endl;
}

猜你喜欢

转载自blog.csdn.net/Joker_He/article/details/108848473