51nod 2026 Gcd and Lcm

51nod 2026 Gcd and Lcm

原题链接

https://www.51nod.com/onlineJudge/questionCode.html#!problemId=2026

题目大意

给你了 f=φ

计算
i=1nj=1nf(gcd(i,j))f(lcm(i,j))

f 明显是积性函数。

则:
f(gcd(i,j))f(lcm(i,j))=f(gcd(i,j))2f(igcd(i,j))f(jgcd(i,j))=f(i)f(j)

i=1nj=1nf(i)f(j)=(i=1nf(i))2

因为 f=φ ,所以:
fφI=fN=eI=I

所以直接套用杜教筛有:

Sf(n)=ni=1niSf(ni)

证明: f=φ

(fφ)(n)=d|nf(n)φ(nd)=d|nt|dμ(t)tandμ(nad)a=a|nknatnakμ(t)tμ(k)a=a|ntnaknatμ(t)tμ(k)a=a|ntnaμ(t)taknatμ(k)at=n0

则:

a|ntnaat=nμ(t)ta=na|nμ(na)=[n=1]

所以:

fφ=e

证明的过程不断替换固定元素。(如果觉得比较玄学。可以用下面的方法代替)

fφ=F

F 必然为积性函数。只需要证明F(Pk)=0,k>0即可

F(Pk)=x+y=kf(Px)φ(Py)=x+y=ki|Pxμ(i)ij|Pyμ(j)Pyj=y=1k1(1P)(PyPy1)+1P+PkPk1

y=1k1(1P)(PyPy1)     

y=1k1(1P)(PyPy1)=(1P)2(1Pk1)1P=(1P)(1Pk1)=1+PPk+Pk1

F(Pk)=1+PPk+Pk1+1P+PkPk1=0

故而:
fφ=e

下面是AC代码:

#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <cmath>
#include <map>
#define MAXN 33336
using namespace std;
typedef long long LL;
const int P=1e9+7;
const int P_=P-1;
int Sf[MAXN];
int mu[MAXN]={0,-1};
int m;
struct H
{
    struct point
    {
        int next,key,p;
        point(int key,int p,int next):key(key),p(p),next(next){}
        point()
        {
            *this=point(0,0,0);
        }
    }E[40008];
    int A[4000008];
    int inof[4000008];
    int deep,cnt;
    H()
    {
        cnt=0;
        deep=0;
        memset(inof,-1,sizeof inof);
    }
    void add(int x,int key,int S)
    {
        A[cnt]=S;
        E[deep]=point(key,cnt++,inof[x]);
        inof[x]=deep++;
    }
    int find(int key)
    {
        int d=key%4000007;
        for(int i=inof[d];i>-1;i=E[i].next)
        {
            point &e=E[i];
            if(e.key==key)return A[e.p];
        }
        return -1;
    }
    void insert(int key,int S)
    {
        add(key%4000007,key,S);
    }
    int operator [](const int key)
    {
        return find(key);
    }

}S;
int A(int n)
{
    if(n&1)
        return (LL)n*((n+1)>>1)%P;
    else
        return (LL)(n>>1)*(n+1)%P;
}
void slove(int n)
{
    int B=sqrt(n)+1;
    int ans=0;
    for(int L=1;L<B;L++)
    {
        ans+=(LL)Sf[L]*(A(n/L)-A(n/(L+1))+P)%P;
        if(ans>P_)ans-=P;
    }
    int lim=n/B+1;
    for(int i=2;i<lim;i++)
    {
        int key=n/i;
        if(key<MAXN)
            ans+=(LL)i*Sf[key]%P;
        else
            ans+=(LL)i*S[n/i]%P;
        if(ans>P_)ans-=P;
    }
    S.insert(n,(n-ans+P)%P);
}

int main ()
{
    for(int i=1;i<MAXN;i++)
    {
        mu[i]=-mu[i];
        for(int j=i<<1;j<MAXN;j+=i)
            mu[j]+=mu[i];
    }
    for(int i=1;i<MAXN;i++)
        for(int j=i;j<MAXN;j+=i)    Sf[j]+=mu[i]*i;
    for(int i=1;i<MAXN;i++)
    {
        Sf[i]+=Sf[i-1];
        if(Sf[i]>P_)Sf[i]-=P;
        if(Sf[i]<0)Sf[i]+=P;
    }
    int n;
    scanf("%d",&n);
    if(n<MAXN)  printf("%d\n",(int)((LL)Sf[n]*Sf[n]%P));
    else
    {
        for(int i=n/MAXN;i>0;i--) slove(n/i);
        printf("%d\n",(int)((LL)S[n]*S[n]%P));
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值