出一个数N,输出小于等于N的所有数,两两之间的最小公倍数之和。
太懒了
这里写的很好
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=10000000+10,maxha=10000000,mo=1000000007,inv2=(mo+1)/2,inv6=(mo+1)/6;
int phi[maxn],pri[maxn],g[maxn];
bool bz[maxn];
int gg[maxn];
ll k,l,t,top,ans;
ll i,j,n,m;
void prepare(){
ll i,j;
phi[1]=1;
fo(i,2,maxn-10){
if (!bz[i]) pri[++top]=i,phi[i]=i-1;
fo(j,1,top){
if ((ll)i*pri[j]>maxn-10) break;
bz[i*pri[j]]=1;
if (i%pri[j]==0){
phi[i*pri[j]]=phi[i]*pri[j];
break;
}
phi[i*pri[j]]=phi[i]*(pri[j]-1);
}
}
fo(i,1,maxn-10) g[i]=(g[i-1]+(ll)phi[i]*i%mo*i%mo)%mo;
}
ll getsum(ll r){
r%=mo;
return (ll)r*(r+1)%mo*((2*r+1)%mo)%mo*inv6%mo;
}
ll calcg(ll n){
if (n<=maxn-10) return g[n];
ll i,j,k;
ll t;
ll l=m/n,r=n%mo;
if (gg[l]) return gg[l];
t=(ll)r*(r+1)%mo*inv2%mo;
t=(ll)t*t%mo;
i=2;
while (i<=n){
j=n/(n/i);
(t-=(ll)(getsum(j)-getsum(i-1))*calcg(n/i)%mo)%=mo;
(t+=mo)%=mo;
i=j+1;
}
return gg[l]=t;
}
int main(){
prepare();
i=1;
scanf("%lld",&n);
m=n;
while (i<=n){
j=n/(n/i);
ans=(ans+(ll)((i+j)%mo)*(j-i+1)%mo*inv2%mo*calcg(n/i)%mo)%mo;
i=j+1;
}
(ans+=mo)%=mo;
printf("%d\n",ans);
}