整除分块,
就对n/i进行求和;
板子:
#include<bits/stdc++.h> using namespace std; long long n,ans; int main() { scanf("%lld",&n); for(int l=1,r;l<=n;l=r+1) { r=n/(n/l); ans+=(r-l+1)*(n/l);//块里都是相等的; cout<<l<<' '<<r<<' '<<ans<<endl; } printf("%lld",ans);}
取模版本:给定n和k,∑ki=1 n%i
首先 n%i=n-(n/i)*i;
然后问题就可以转化成整除分块问题(n*k-∑ki=1(n/i)*i),卡在了取模里 嗷嗷嗷
对每一个块来讲,等差数列求个和(r-l+1)*(l+r)/2*(n/l);
写一个取模函数即可;
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
#include <set>
#include <map>
typedef long long ll;
const int N=100000+100;
const int mod=1e9+7;
using namespace std;
ll a,b;
ll sum=0,ans=0;
ll mult(ll a,ll b)
{
return ((a%mod)*(b%mod))%mod;
}
int main()
{
scanf("%lld %lld",&a,&b);
sum=mult(a,b);
b=min(a,b);
ll l,r;
for(ll i=1;i<=b;i=r+1)
{
l=i,r=a/(a/i);
r=min(r,b);//最后一个区域的边界问题
ll cc=0;
if((l+r)&1) cc=mult(l+r,(r-l+1)/2);//如果为奇数
else cc=mult((l+r)/2,r-l+1);
ans+=mult(cc,a/l);
ans%=mod;
//i=r;
}
sum-=ans;
if(sum<0) sum+=mod;
printf("%lld
",sum);
return 0;}
取模时要奇数和偶数分开取模;