bzoj2226 LCMSum

来源:互联网 发布:位图转矢量图软件 编辑:程序博客网 时间:2024/06/03 16:33

Description Given n, calculate the sum LCM(1,n) + LCM(2,n) + .. +
LCM(n,n), where LCM(i,n) denotes the Least Common Multiple of the
integers i and n. Input The first line contains T the number of test
cases. Each of the next T lines contain an integer n. Output Output T
lines, one for each test case, containing the required sum.

======i=1nlcm(i,n)ni=1nigcd(i,n)nd|ngcd(kd,n)=dkddnd|ngcd(k,nd)=1kn(g×1)n2((idφ+e)×1)n2((idφ)×1+1)

其中

g(n)=i=1nie(gcd(i,n))=i=1nid|gcd(i,n)μ(d)       (e=1×μ)=d|nμ(d)in,d|ii=d|nμ(d)n(nd+1)2=n2(d|nμ(d)nd+d|nμ(d))=n2(μ×id+μ×1)=n2(φ+e)       (φ=μ×id)=idφ+e2

g=(idφ)×1是积性函数,可以线性筛。当n|p时,

======g(np)g(pmqp)g(pm+1)g(q)g(q)i=0m+1φ(pi)pig(q)(i=0mφ(pi)pi+φ(pm+1)pm+1)g(q)(g(pm)+(p1)p2m+1)       (φ(pk)=(p1)pk1)g(n)+(p1)p2m+1g(q)

在线性筛的时候顺便记下每个数最小质因子的幂,可以O(1)地算出p2m+1q,这样时间复杂度就是O(n+q)

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define LL long longconst int maxn=1000000;LL g[1000010];int prm[1000010],tot,pow[1000010];int rd(){    int x=0;    char c=getchar();    while (c<'0'||c>'9') c=getchar();    while (c>='0'&&c<='9')    {        x=x*10+c-'0';        c=getchar();    }    return x;}void init(){    int i,j;    g[1]=1;    for (i=2;i<=maxn;i++)    {        if (!g[i])        {            prm[++tot]=i;            g[i]=(LL)i*(i-1)+1;            pow[i]=i;        }        for (j=1;j<=tot&&(LL)i*prm[j]<=maxn;j++)          if (i%prm[j]==0)          {            g[i*prm[j]]=g[i]+(LL)(prm[j]-1)*pow[i]*pow[i]*prm[j]*g[i/pow[i]];            pow[i*prm[j]]=pow[i]*prm[j];            break;          }          else          {            g[i*prm[j]]=g[i]*g[prm[j]];            pow[i*prm[j]]=prm[j];          }    }}int main(){    int T,x;    init();    T=rd();    while (T--)    {        x=rd();        printf("%lld\n",(g[x]+1)*x/2);    }}
0 0