ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

HDU 6134 Battlestation Operational(莫比乌斯反演)

2021-05-08 19:00:23  阅读:208  来源: 互联网

标签:prime lfloor HDU frac limits sum 6134 Operational ll


HDU 6134 Battlestation Operational(莫比乌斯反演)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6134
题目大意:给定正整数 n n n ,求 ∑ i = 1 n ∑ j = 1 i ⌈ i j ⌉ [ gcd ⁡ ( i , j ) = 1 ] ( 1 ≤ n ≤ 1 e 6 ) \sum\limits_{i=1}^n\sum\limits_{j=1}^i\lceil\frac{i}{j}\rceil[\gcd(i,j)=1](1\leq n\leq 1e6) i=1∑n​j=1∑i​⌈ji​⌉[gcd(i,j)=1](1≤n≤1e6) ,其中 ⌈ x ⌉ \lceil x\rceil ⌈x⌉ 为上取整符号。
题解:先转化一下式子:

⇒ ∑ i = 1 n ∑ j = 1 i ⌈ i j ⌉ ε ( gcd ⁡ ( i , j ) ) \Rightarrow\sum\limits_{i=1}^n\sum\limits_{j=1}^i\lceil\frac{i}{j}\rceil\varepsilon(\gcd(i,j)) ⇒i=1∑n​j=1∑i​⌈ji​⌉ε(gcd(i,j))

= ∑ i = 1 n ∑ j = 1 i ⌈ i j ⌉ ∑ t ∣ i , t ∣ j μ ( t ) =\sum\limits_{i=1}^n\sum\limits_{j=1}^i\lceil\frac{i}{j}\rceil\sum\limits_{t\mid i,t\mid j}\mu(t) =i=1∑n​j=1∑i​⌈ji​⌉t∣i,t∣j∑​μ(t)

= ∑ t = 1 n μ ( t ) ∑ i = 1 ⌊ n t ⌋ ∑ j = 1 i ⌈ i j ⌉ =\sum\limits_{t=1}^{n}\mu(t)\sum\limits_{i=1}^{\lfloor\frac{n}{t}\rfloor}\sum\limits_{j=1}^i\lceil\frac{i}{j}\rceil =t=1∑n​μ(t)i=1∑⌊tn​⌋​j=1∑i​⌈ji​⌉

考虑上取整的意义,当 j ∣ i j\mid i j∣i 时, ⌈ i j ⌉ = ⌊ i j ⌋ \lceil\frac{i}{j}\rceil=\lfloor\frac{i}{j}\rfloor ⌈ji​⌉=⌊ji​⌋ ,反之当 j ∤ i j\nmid i j∤i 时,有 ⌈ i j ⌉ = ⌊ i j ⌋ + 1 \lceil\frac{i}{j}\rceil=\lfloor\frac{i}{j}\rfloor+1 ⌈ji​⌉=⌊ji​⌋+1 。那么式子可以继续转化一下:

⇒ ∑ t = 1 n μ ( t ) ∑ i = 1 ⌊ n t ⌋ ∑ j = 1 i ( ⌊ i j ⌋ + [ j ∤ i ] ) \Rightarrow\sum\limits_{t=1}^{n}\mu(t)\sum\limits_{i=1}^{\lfloor\frac{n}{t}\rfloor}\sum\limits_{j=1}^i(\lfloor\frac{i}{j}\rfloor+[j\nmid i]) ⇒t=1∑n​μ(t)i=1∑⌊tn​⌋​j=1∑i​(⌊ji​⌋+[j∤i])
= ∑ t = 1 n μ ( t ) ∑ i = 1 ⌊ n t ⌋ ( i − τ ( i ) + ∑ j = 1 i ⌊ i j ⌋ ) =\sum\limits_{t=1}^{n}\mu(t)\sum\limits_{i=1}^{\lfloor\frac{n}{t}\rfloor}(i-\tau(i)+\sum\limits_{j=1}^i \lfloor\frac{i}{j}\rfloor) =t=1∑n​μ(t)i=1∑⌊tn​⌋​(i−τ(i)+j=1∑i​⌊ji​⌋)

其中 τ ( n ) \tau(n) τ(n) 为约数个数函数,且 τ ( i ) \tau (i) τ(i) 是可以线性筛预处理的。那么我们只要处理 ∑ i = 1 ⌊ n t ⌋ ∑ j = 1 i ⌊ i j ⌋ \sum\limits_{i=1}^{\lfloor\frac{n}{t}\rfloor}\sum\limits_{j=1}^i \lfloor\frac{i}{j}\rfloor i=1∑⌊tn​⌋​j=1∑i​⌊ji​⌋ 这一部分即可。再考虑下取整的意义,不难发现,对于 ∀ k ∈ Z + , ⌊ k j j ⌋ = ⌊ k j + 1 j ⌋ = ⌊ k j + 2 j ⌋ = ⋯ = ⌊ ( k + 1 ) j − 1 j ⌋ \forall k \in \mathbb{Z^{+}},\lfloor\frac{kj}{j}\rfloor=\lfloor\frac{kj+1}{j}\rfloor=\lfloor\frac{kj+2}{j}\rfloor=\cdots=\lfloor\frac{(k+1)j-1}{j}\rfloor ∀k∈Z+,⌊jkj​⌋=⌊jkj+1​⌋=⌊jkj+2​⌋=⋯=⌊j(k+1)j−1​⌋ ,那么对于区间 [ k j , ( k + 1 ) j − 1 ] [kj,(k+1)j-1] [kj,(k+1)j−1] ,同时加上值 k k k 即可。这里存在区间修改的问题,那么我们使用差分的技巧在原始的埃式筛中处理,再作两次前缀和即可,此时预处理复杂度为 O ( n l o g n ) O(nlogn) O(nlogn) 。
最后用数论分块处理就行。

#include<bits/stdc++.h>
using namespace std;
#define debug(x) cerr<<#x<<":"<<x<<endl
#define debug2(x,y) cerr<<#x<<":"<<x<<"  "<<#y<<":"<<y<<endl
#define debug3(x,y,z) cerr<<#x<<":"<<x<<"  "<<#y<<":"<<y<<"  "<<#z<<":"<<z<<endl
typedef long long ll;
const int MAX=1e6+5;
const ll M=1e9+7;
int cnt=0;
int D[MAX],S[MAX],SS[MAX],tao[MAX],minp_v[MAX],part[MAX],prime[MAX],ST[MAX],mu[MAX],SM[MAX];
void pre(){
    SM[0]=mu[0]=ST[0]=tao[0]=D[0]=S[0]=SS[0]=0;
    memset(D,0,sizeof(D));
    memset(mu,0,sizeof(D));
    for(int j=1;j<MAX;++j){
        for(int i=1;i*j<MAX;++i){
            int l=i*j,r=(i+1)*j;
            D[l]+=i;
            if(r<MAX) D[r]-=i;
        }
    }
    for(int i=1;i<MAX;++i) S[i]=(S[i-1]+D[i])%M;
    SS[1]=S[1];
    tao[1]=SM[1]=mu[1]=1;
    ST[1]=0;
    for(int i=2;i<MAX;++i){
        if(!part[i]){
            part[i]=i;
            prime[cnt++]=i;
            minp_v[i]=tao[i]=2;
            mu[i]=-1;
        }
        SS[i]=((ll)SS[i-1]+(ll)S[i])%M;
        ST[i]=((ll)ST[i-1]+(ll)i-(ll)tao[i])%M;
        SM[i]=((ll)SM[i-1]+(ll)mu[i])%M;
        for(int j=0;i*prime[j]<MAX;++j){
            part[i*prime[j]]=prime[j];
            if(i%prime[j]){
                tao[i*prime[j]]=tao[i]*tao[prime[j]];
                minp_v[i*prime[j]]=2;
                mu[i*prime[j]]=-mu[i];
            }
            else{
                tao[i*prime[j]]=tao[i]/minp_v[i];
                minp_v[i*prime[j]]=minp_v[i]+1;
                tao[i*prime[j]]*=minp_v[i*prime[j]];
                break;
            }
        }
    }
}
int main(){
    pre();
    int n;
    while(cin>>n){
        ll res=0;
        for(ll l=1,r;l<=n;l=r+1){
            r=n/(n/l);
            res=(res+((ll)SM[r]-(ll)SM[l-1])%M*(((ll)ST[n/l]+(ll)SS[n/l])%M)%M)%M;
        }
        if(res<0) res+=M;
        cout<<res<<endl;
    }
}

意外的,时间并没有超过1秒(题目给了3秒)。
在这里插入图片描述

标签:prime,lfloor,HDU,frac,limits,sum,6134,Operational,ll
来源: https://blog.csdn.net/m0_52639539/article/details/116537057

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有