51nod1238(杜教筛)

这个题暴露出杜教筛还是没掌握好。。

\sum_{i=1}^{n}\sum_{j=1}^{n}[i,j]\\= 2\sum_{i=1}^{n}\sum_{j=1}^{i}[i,j]-\sum_{i=1}^{n}i\\= 2\sum_{i=1}^{n}\sum_{j=1}^{i}\frac{ij}{(i,j)}-\sum_{i=1}^{n}i\\= 2\sum_{i=1}^{n}i\sum_{j=1}^{i}\frac{j}{(i,j)}-\sum_{i=1}^{n}i

然后就是讨论一个常见的求和

\sum_{i=1}^{n}\frac{i}{(i,n)}= \sum_{d|n}\sum_{i=1}^{n}\frac{i}{d}[gcd(\frac{i}{d},\frac{n}{d})=1]= \frac{1}{2}(\sum_{d|n}d\varphi(d)+1)

然后原式就能化简成

\sum_{i=1}^{n}\sum_{j=1}^{n}[i,j]= \sum_{i=1}^{n}i\sum_{d|i}d\varphi(d)

然后窝就天真的吧这个和式拿去做杜教筛了。。。然而这个和式的一个问题是函数也是个和式,其卷积实在是难求,所以推到一半推不下去,参考别人的题解转化了下思路,枚举一下倍数,就变成。。。

\sum_{i=1}^{n}\sum_{j=1}^{n}[i,j]\\= \sum_{i=1}^{n}i\sum_{d|i}d\varphi(d)\\= \sum_{i=1}^{n}\sum_{d|i}\frac{i}{d}d^2\varphi(d)\\= \sum_{i=1}^{n}i\sum_{d=1}^{\left \lfloor \frac{n}{i} \right \rfloor}d^2\varphi(d)

然后令f(n)=n^2\varphi(n),F(n)为其前缀和,即求

\sum_{i=1}^{n}iF(\left \lfloor \frac{n}{i} \right \rfloor)

再求f(n)的卷积

\sum_{d|n}f(d)(\frac{n}{d})^2=n^2\sum_{d|n}\varphi(d)=n^3

F(n)=\sum_{i=1}^{n}f(i)=\sum_{i=1}^{n}(i^3-\sum_{d|i}^{d<i}d^2f(d))=\frac{n^2(n+1)^2}{4}-\sum_{i=2}^{n}i^2F(\left \lfloor \frac{n}{i} \right \rfloor)

最终貌似要求好多个F(n)实际上都是F(\left \lfloor \frac{n}{d} \right \rfloor)这种形式,这些在杜教筛的时候其实已经都求过了。。

然后分块求+预处理复杂度O(n^{\frac{2}{3}})

 

 

 

 

/**
 *          ┏┓    ┏┓
 *          ┏┛┗━━━━━━━┛┗━━━┓
 *          ┃       ┃  
 *          ┃   ━    ┃
 *          ┃ >   < ┃
 *          ┃       ┃
 *          ┃... ⌒ ...  ┃
 *          ┃              ┃
 *          ┗━┓          ┏━┛
 *          ┃          ┃ Code is far away from bug with the animal protecting          
 *          ┃          ┃   神兽保佑,代码无bug
 *          ┃          ┃           
 *          ┃          ┃        
 *          ┃          ┃
 *          ┃          ┃           
 *          ┃          ┗━━━┓
 *          ┃              ┣┓
 *          ┃              ┏┛
 *          ┗┓┓┏━━━━━━━━┳┓┏┛
 *           ┃┫┫       ┃┫┫
 *           ┗┻┛       ┗┻┛
 */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-8
#define succ(x) (1LL<<(x))
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define mid ((x+y)/2) 
#define NM 5000005
#define nm 10005
#define N 1000005
#define M(x,y) x=max(x,y)
const double pi=acos(-1);
const ll inf=1e9+7;
using namespace std;
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}








ll _x,ans,f[NM],b[NM],inv2,inv4,inv6;
bool v[NM];
int m,prime[NM],phi[NM],tot;

ll qpow(ll x,ll t){return t?qpow(sqr(x)%inf,t>>1)*(t&1?x:1)%inf:1LL;}

void init(){
    m=4700000;phi[1]=f[1]=1;
    inc(i,2,m){
	if(!v[i])prime[++tot]=i,phi[i]=i-1;
	inc(j,1,tot){
	    if(i*prime[j]>m)break;
	    v[i*prime[j]]++;
	    if(i%prime[j]==0){phi[i*prime[j]]=phi[i]*prime[j];break;}
	    phi[i*prime[j]]=phi[i]*(prime[j]-1);
	}
	f[i]=(ll)i*i%inf*phi[i]%inf;f[i]+=f[i-1];f[i]%=inf;
    }
    inv4=qpow(4,inf-2);inv2=qpow(2,inf-2);inv6=qpow(6,inf-2);
}

ll sum(ll n){return (n%inf)*((2*n+1)%inf)%inf*((n+1)%inf)%inf*inv6%inf;}

ll F(ll n){
    if(n<=m)return f[n];
    int t=_x/n;
    if(v[t])return b[t];
    v[t]++;b[t]=(n%inf)*(n%inf)%inf*((n+1)%inf)%inf*((n+1)%inf)%inf*inv4%inf;
    for(ll i=2,j;i<=n;i=j+1){
	j=n/(n/i);
	b[t]+=inf-(sum(j)-sum(i-1)+inf)*F(n/i)%inf;b[t]%=inf;
    }
    return b[t];
}



int main(){
    init();_x=read();mem(v);
    for(ll i=1,j;i<=_x;i=j+1){
	j=_x/(_x/i);
	ans+=(i+j)%inf*((j-i+1)%inf)%inf*inv2%inf*F(_x/i)%inf;ans%=inf;
    }
    return 0*printf("%lld\n",ans);
}

 

 

 

1238 最小公倍数之和 V3

基准时间限制:8 秒 空间限制:262144 KB 分值: 640 难度:8级算法题

收藏

关注

出一个数N,输出小于等于N的所有数,两两之间的最小公倍数之和。

 

相当于计算这段程序(程序中的lcm(i,j)表示i与j的最小公倍数):

由于结果很大,输出Mod 1000000007的结果。

 

G=0;

for(i=1;i

for(j=1;j<=N;j++)

{

    G = (G + lcm(i,j)) % 1000000007;

}

Input

输入一个数N。(2 <= N <= 10^10)

Output

输出G Mod 1000000007的结果。

Input示例

4

Output示例

72

你可能感兴趣的:(数论)