HDU5382 GCD?LCM!

来源:互联网 发布:网络映射有什么用 编辑:程序博客网 时间:2024/06/04 01:22

题目链接

题目大意

令:

F(n)=i=1nj=1n[lcm(i,j)+gcd(i,j)n],S(n)=i=1nF(i).

T次询问S(n) mod 258280327的值.

T105,n106.

题解

又是这种一看题解就觉得自己也能推的数论题….

首先看数据范围,目测是先预处理所有答案然后O(1)询问的.
那么预处理时肯定要考虑F(n)F(n1)的关系.

F(n)=i=1nj=1n[lcm(i,j)+gcd(i,j)n]=i=1nj=1n[lcm(i,j)+gcd(i,j)n1]i=1nj=1n[lcm(i,j)+gcd(i,j)=n1].

G(n)=ni=1nj=1[lcm(i,j)+gcd(i,j)=n],先把这个放在一边.

比较上面得到的这个东西左边那个二重和式和F(n1)的表达式,我们可以把其中i=n或者j=n的情况特殊讨论一下,容易得到此时一定满足lcm(i,j)+gcd(i,j)n1,于是上式就变成了这样:

F(n)=F(n1)+2n1G(n1).

然后再来推G(n),这里运用的还是通常的枚举gcd的思路:

G(n)=i=1nj=1n[lcm(i,j)+gcd(i,j)=n]=d=1ni=1ndj=1nd[ij][ijd+d=n]=dni=1ndj=1nd[ij][ij=nd1]=dnH(nd1).

其中

H(n)=dn[dnd].

喜闻乐见的是H(n)是个积性函数,可以愉快地线性筛.
具体来说是这样的:
对素数p,H(pk)=2(k1).
考虑筛到prod=iprime[j]时,prime[j]prod的最小素因子,H(prod)H(i)的关系.
i=kprime[j]t(kprime[j]),那么H(k)=H(i)2,prod=kprime[j]t+1.
d满足dkd,D满足DprodD.
那么D的约数中要么不包含prime[j],即Dd一一对应,方案数有H(k)=H(i)2种;要么包含prime[j]t+1,即D=dprime[j]t+1,所以这样的Dd也存在一一对应关系,方案数也是H(k)=H(i)2.
所以H(prod)=H(i).

然后可以O(nlnn)计算出G(n),再O(n)计算F(n)S(n),就做完了.

代码

#include<cstdio>#include<cstring>const int N=1e6+5,mod=258280327;int prime[N],H[N],G[N],F[N],S[N];bool is_prime[N];void sieve(){    memset(is_prime,true,N);    H[1]=1;    for(int i=2,tot_prime=0;i<N;++i){        if(is_prime[i]){            prime[tot_prime++]=i;            H[i]=2;        }        for(int j=0,prod;j<tot_prime&&(prod=i*prime[j])<N;++j){            is_prime[prod]=false;            if(i%prime[j])H[prod]=H[i]<<1;            else{                H[prod]=H[i];                break;            }        }    }}inline void mod_add(int &a,int b){    if((a+=b)>=mod)a-=mod;}void solve(){    sieve();    memset(G,0,N<<2);    for(int d=1;d<N;++d){        for(int k=1,n;(n=k*d)<N;++k){            mod_add(G[n],H[k-1]);        }    }    F[1]=S[1]=1;    for(int n=2;n<N;++n){        F[n]=((F[n-1]+(n<<1)-1-G[n-1])%mod+mod)%mod;        if((S[n]=S[n-1]+F[n])>=mod)S[n]-=mod;    }}inline void rd(int &res){    res=0;    char c;    while(c=getchar(),c<48);    do res=(res<<3)+(res<<1)+(c^48);        while(c=getchar(),c>47);}int main(){    int cas,n;    rd(cas);    solve();    while(cas--){        rd(n);        printf("%d\n",S[n]);    }    return 0;}/*    Jul.05.16    Tags:number theory,sieve    Submissions:1    Memory(KB) 18340    Time(ms) 234    Length(Bytes) 990*/
0 0
原创粉丝点击