首页 > 其他分享 >数论函数

数论函数

时间:2023-08-03 20:22:18浏览次数:39  
标签:lfloor frac 函数 数论 sum rfloor mu gcd

P1390公约数的和

简单莫反题。要求

\[\sum_{i=1}^{n}\sum_{j=i+1}^ngcd(i,j) \]

可以先考虑问题的简化版:

\[\sum_{i=1}^{n}\sum_{j=1}^ngcd(i,j) \]

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

\[=\sum_{d=1}^nd\sum_{i=1}^{\lfloor \frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor \frac{n}{d}\rfloor}[gcd(i,j)==1] \]

\[=\sum_{d=1}^nd\sum_{i=1}^{\lfloor \frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor \frac{n}{d}\rfloor}\sum_{k|gcd(i,j)}^{gcd(i,j)} \mu(k) \]

\[=\sum_{d=1}^nd\sum_{i=1}^{\lfloor \frac{n}{d}\rfloor}\mu(i)\sum_{i|j}^{\lfloor \frac{n}{d}\rfloor} \sum_{i|k}^{\lfloor \frac{n}{d}\rfloor}1 \]

\[=\sum_{d=1}^nd\sum_{i=1}^{\lfloor \frac{n}{d}\rfloor}\mu(i)\sum_{i|j}^{\lfloor \frac{n}{d}\rfloor} \sum_{i|k}^{\lfloor \frac{n}{d}\rfloor}1 \]

\[=\sum_{d=1}^nd\sum_{i=1}^{\lfloor \frac{n}{d}\rfloor}\mu(i)\lfloor \frac{n}{di}\rfloor^2 \]

然后用一个数论分块,就可以求出该柿子。

再考虑题目中要求我们算的柿子,设它为\(ans\)。

不难发现\(\sum_{i=1}^{n}\sum_{j=1}^ngcd(i,j)=ans\times 2+\sum_{i=1}^{n}gcd(i,i)=ans\times 2+\frac{n\times (n+1)}{2}\)

然后就能愉快地求出来了。

P1447能量采集

不难发现,题目让我们求的是\(\sum_{i=1}^{n}\sum_{j=1}^{m}2\times gcd(i,j)-n\times m\)

于是就转化成为了上一题。\(ans=2\times \sum_{d=1}^nd\sum_{i=1}^{\lfloor \frac{n}{d}\rfloor}\mu(i)\lfloor \frac{n}{di}\rfloor\lfloor \frac{m}{di}\rfloor -n\times m\)(这里假定\(n>=m\))

YY的GCD

莫反\(+\)一个小优化。先假定\(n>=m\)。仍是按照第一题的方式推柿子,\(ans=\sum_{d=1}^n\sum_{i=1}^{\lfloor \frac{n}{d}\rfloor}\mu(i)\lfloor \frac{n}{di}\rfloor\lfloor \frac{m}{di}\rfloor(d\in prime)\)

然而这样复杂度是\(O(n\space logn)\)的,仍会超时,肿么办?

注意到,数对 \((i,d)\) 相当于枚举了所有乘积小于等于 \(n\) 的数(且后一个数是质数)。令 \(T=i\times d\),考虑枚举每一个 \(T\) 对答案有多少贡献(这是一个套路,后面会经常用):

\[ans=\sum_{T=1}^n\lfloor \frac{n}{T}\rfloor\lfloor \frac{m}{T}\rfloor\sum_{k|T,k\in prime}^{} \mu( \frac{T}{k}) \]

然后发现, \(\sum_{k|T,k\in prime}^{} \mu( \frac{T}{k})\) 是可以预处理的。枚举每一个质数 \(p\) ,然后令它的倍数 \(k\) 加上 \(\mu(\frac{k}{p})\) 。

\(code:\)

void work(){
	ll r=0,a=n,b=m;
	if(a<b) swap(a,b);
	for(int i=1;i<=b;i=r+1){
		r=min(a/(a/i),b/(b/i));
		if(r>b) r=b;
		ans+=(sum[r]-sum[i-1])*(a/i)*(b/i);//注意是a/i下取整,要加括号 
	}
}
int main(){
	for(int i=1;i<=maxn;++i)
		miu[i]=1;
	for(int i=2;i<=maxn;++i){
		if(!vis[i]){
			p[++tot]=i,miu[i]=-1;
			for(int j=i*2;j<=maxn;j+=i){
				vis[j]=1;
				if(j/i%i==0) miu[j]=0;
				else miu[j]*=-1;
			}
		}
	}
	for(int i=1;i<=maxn;++i)
		for(int j=1;p[j]*i<=maxn&&j<=tot;++j)
			s[i*p[j]]+=miu[i];
	for(int i=1;i<=maxn;++i)
		sum[i]=sum[i-1]+s[i];
	scanf("%lld",&t);
	while(t--){
		scanf("%lld%lld",&n,&m);
		ans=0;
		work();
		printf("%lld\n",ans);
	}
	return 0;
}

P3327约数个数和

前言:一些常用的二级结论:

\[\mu(ij)=\mu(i)\mu(j)[gcd(i,j)==1] \]

\[d(ij)=\sum_{x|i}\sum_{y|j}[gcd(x,y)==1] \]

\[\phi(ij)=\frac{\phi(i)\phi(j)gcd(i,j)}{\phi(gcd(i,j))} \]

推柿子参看题解区

然后令\(F(n)=\sum_{i=1}^n\lfloor\frac{n}{i}\rfloor\),则

\[ans=\sum_{g=1}^{\min(n,m)}\mu(g)\cdot F(\lfloor\frac{n}{g}\rfloor)\cdot F(\lfloor\frac{m}{g}\rfloor) \]

然后用数论分块即可。时间复杂度 \(O(n\space \sqrt n+T\space \sqrt n)\) 。

\(code;\)

void work(){
    scanf("%lld%lld",&n,&m);
    if(n<m)
        swap(n,m);
    int ans=0;
    for(int i=1,r=0,rr=0;i<=m;i=r+1){
        r=n/(n/i);rr=m/(m/i);//cout<<r<<" "<<rr<<endl;
        r=min(r,min(rr,m));//cout<<m/i<<" "<<m/r<<" "<<n/i<<" "<<n/r<<endl;
        ans+=(miu[r]-miu[i-1])*s[m/i]*s[n/i];
    }
    printf("%lld\n",ans);
}
signed main(){
    scanf("%lld",&t);
    for(int i=2;i<=100000;++i){
        if(a[i]==0)
            p[++tot]=i,a[i]=i;
        for(int j=1;j<=tot;++j){
            if(i*p[j]>100000||a[i]<p[j])
                break;
            a[i*p[j]]=p[j];
        }
    }
    for(int i=1;i<=100000;++i)
        miu[i]=1;
    for(int i=2;i<=100000;++i){
        int tmp=i/a[i];
        if(tmp%a[i]==0)
            miu[i]=0;
        else
            miu[i]=-miu[tmp];
    }
    for(int i=1;i<=100000;++i)
        miu[i]+=miu[i-1];
    for(int i=1;i<=100000;++i){
        for(int j=1,r=0;j<=i;j=r+1){
            r=i/(i/j);
            s[i]+=(r-j+1)*(i/j);
        }
    }
    while(t--)
        work();
    //for(int i=1;i<=100;++i)cout<<miu[i]<<" ";cout<<endl;
    return 0;
}

P3768简单的数学题

利用 \(\phi*1=id\) 可以得到:

\[\sum_{d=1}^{n}F^2(\lfloor \frac{n}{d}\rfloor)\cdot d^2\phi(d) \]

其中 \(F(n)=n\times (n+1)/2\)

其中 \(\sum_{d=1}^{n}F^2(\lfloor \frac{n}{d}\rfloor)\) 可以用数论分块处理,剩下的部分考虑杜教筛。

剩下的部分是 \(d^2\phi(d)\) ,设 \(\sum_{d=1}^{n}d^2\phi(d)\) 为 \(s(n)\) ,考虑构造函数 \(g(n)=n^2\) ,则有:

\[s(n)=\sum_{i=1}^{n}((id^2 \phi)*g)(i)-\sum_{i=2}^{n}id^2(i)s(\lfloor \frac{n}{i}\rfloor) \]

化简得到:

\[s(n)=(\frac {n\times (n+1)}{2})^2-\sum_{i=2}^{n}i^2s(\lfloor \frac{n}{i}\rfloor) \]

P3312数表

先不考虑 \(a\) 的限制,有:

\[ans=\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{k|gcd(i,j)}k \]

\[=\sum_{i=1}^{n}\sum_{j=1}^{m}f(gcd(i,j)) \]

\[=\sum_{d=1}^{n}\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}f(d)[gcd(i,j)==d] \]

\[=\sum_{d=1}^{n}\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}f(d)\sum_{k|gcd(i,j)}\mu(k) \]

\[=\sum_{d=1}^{n}f(d)\sum_{k=1}^{\lfloor\frac{m}{d}\rfloor}\mu(k)\lfloor\frac{n}{dk}\rfloor\lfloor\frac{m}{dk}\rfloor \]

\[=\sum_{t=1}^{m}\lfloor\frac{n}{t}\rfloor\lfloor\frac{m}{t}\rfloor\sum_{kd=t}\mu(k)f(d) \]

(其中 \(f(x)\) 表示 \(x\) 的因数和,可以预处理得到)

接下来考虑 \(a\) 。首先将询问按照 \(a\) 从小到大排序,然后开一个树状数组(其中单点\(i\)表示 \((f*\mu)(i)\) ),每次遇到可以加入树状数组的 \(f(i)\) ,就枚举 \(i\) 的倍数,令 \(ki\) 的单点数值增加 \(f(i)\times\mu(k)\) 。然后在数论分块的时候,如果当前区间为 \([l,r]\) ,就让 \(ans\) 乘以 \([l,r]\) 的区间和。

\(code:\)

bool cmp(node a,node b){
    return a.a<b.a;
}
bool cmp2(node a,node b){
    return a.w<b.w;
}
void add(long long x,long long w){
    while(x<=L)
        c[x]=(c[x]+w)%mod,x+=x&(-x);
}
long long ask(long long x){
    long long re=0;
    while(x)
        re=(re+c[x])%mod,x-=x&(-x);
    return re;
}
long long work(long long n,long long m){
    int ans=0;
    if(n<m)
        swap(n,m);
    for(int i=1,r=0;i<=m;i=r+1){
        r=min(n/(n/i),min(m/(m/i),m));
        ans=(ans+((n/i)%mod*(m/i)%mod*((ask(r)-ask(i-1)+mod)%mod)%mod))%mod;
    }
    return ans;
}
void pre_work(){
	for(int i=2;i<=L;++i){
		if(a[i]==0)
			a[i]=i,prime[++tot]=i;
		for(int j=1;j<=tot;++j){
			if(prime[j]*i>L||prime[j]>a[i])
				break;
			a[i*prime[j]]=prime[j];
		}
	}
	miu[1]=1;
	for(int i=2;i<=L;++i){
		int j=i/a[i];
		if(j%a[i]==0)
			miu[i]=0;
		else
			miu[i]=miu[j]*(-1);
	}
    for(int i=1;i<=tot;++i){
        long long now=prime[i];
        p[now][0]=sum[now][0]=1;
        long long tmp=0;
        while(sum[now][tmp]<=L){
            ++tmp;
            p[now][tmp]=p[now][tmp-1]*prime[i];
            sum[now][tmp]=(sum[now][tmp-1]+p[now][tmp]);
        }
    }
    for(int i=1;i<=L;++i){
        long long tmp=i,cnt=0;
        f[i].w=1;f[i].id=i;
        for(int j=1;j<=tot&&prime[j]*prime[j]<=i;++j){
            cnt=0;
            while(tmp%prime[j]==0)
                tmp/=prime[j],++cnt;
            f[i].w=f[i].w*sum[prime[j]][cnt];
        }
        if(tmp!=1)
            f[i].w=f[i].w*sum[tmp][1];
    }
    sort(f+1,f+L+1,cmp2);
}
signed main(){
    pre_work();
	scanf("%lld",&t);
    for(int i=1;i<=t;++i)
        scanf("%lld%lld%lld",&v[i].n,&v[i].m,&v[i].a),v[i].id=i;
    sort(v+1,v+t+1,cmp);
    for(int i=1,j=1;i<=t;++i){
        while(j<=L&&f[j].w<=v[i].a){
            for(int k=f[j].id;k<=L;k+=f[j].id)
                add(k,f[j].w*miu[k/f[j].id]%mod);
            ++j;
        }
        ans[v[i].id]=work(v[i].n,v[i].m);
    }
    for(int i=1;i<=t;++i)
        printf("%lld\n",ans[i]);
	return 0;
}

标签:lfloor,frac,函数,数论,sum,rfloor,mu,gcd
From: https://www.cnblogs.com/andyl/p/17604360.html

相关文章

  • 基于GPT搭建私有知识库聊天机器人(五)函数调用
    文章链接:基于GPT搭建私有知识库聊天机器人(一)实现原理基于GPT搭建私有知识库聊天机器人(二)环境安装基于GPT搭建私有知识库聊天机器人(三)向量数据训练基于GPT搭建私有知识库聊天机器人(四)问答实现OpenAI在6月13日发布了几个重磅更新,其中包括:开放了16k上下文的GPT-3.5-Turbo模型gpt-3.5-t......
  • Linux环境编程--功能函数编写1
    Linux系统编程实例11.实现一个计算文件大小的函数方法1(标准IO):函数使用:intfseek(FILE*stream,longoffset,intwhence);返回值:成功0失败-1longintftell(FILE*stream);返回值:返回位置标识符的当前值。如果发生错误,则返回-1Llongfile_size(constchar*path){......
  • Excel中Hyperlink函数的使用
    Hyperlink函数是将文本形式的链接转换为超链接。调用格式:=HYPERLINK(链接,标题)或者:=HYPERLINK(链接)具体可参考Hyperlink函数Microsoft官方文档视频演示:......
  • jQuery--常用函数
    1、val 操作数组中的DOM对象的value属性//无参形式,读取数组中第一个dom对象的value值$(选择器).val()//有参形式,对数组中所有dom对象的value属性值统一赋值$(选择器).val(值)2、text操作数组中所有dom对象的文字内容属性//无参形式,读取数组中所有dom对象的文字显示内......
  • 箭头函数和普通函数的区别
    1、普通函数定义:编程中常见的一种函数类型,也被称为一般函数或普通方法。它们是一系列执行特定任务的代码块或子程序。普通函数通常包含输入参数和返回值,用于接收输入数据、进行处理,并返回结果。//这里的name是指函数名(自取)functionname(参数){//函......
  • isinstance()函数可以用于类型检查
    x=5print(isinstance(x,int))#True,x是int类型的对象y="Hello"print(isinstance(y,str))#True,y是str类型的对象z=[1,2,3]print(isinstance(z,list))#True,z是list类型的对象a=3.14print(isinstance(a,(int,float)))#True,a是int或float类型的......
  • Qt中QString的arg()函数
    Qt中QString的arg()函数使用记录大致有如下3种用法:(1)arg(str1,str2,str3)其中一次可替换参数个数最多为9个,举例如下 输出为"123456789%10%11"要想全部替换,只需要接在后面继续使用一个.arg(“10”,“11”)即可也就是第二种方式(2)arg(str1).arg(str2).arg(s......
  • python教程 入门学习笔记 第5天 format函数拼接 两种打印方法 转义字符
    2)format函数拼接#format函数拼接s1="统计={0}{1}{2}".format("张三","工资",3400)#占位符{}中可以填写数字编号print(s1)s2="统计={}{}{}".format("李四","工资",4500)#用占位符{}拼接,占位符要与字符串数量一致print(s2)s3="统计={a}{b}{c}".forma......
  • 2.为什么析构函数一般写成虚函数
    2.为什么析构函数一般写成虚函数在C++实现多态里,有一个关于析构函数的重写问题:基类中的析构函数如果是虚函数,那么派生类的析构函数就重写了基类的析构函数。这里他们的函数名不相同,看起来违背了重写的规则,但实际上编译器对析构函数的名称做了特殊处理,编译后析构函数的名称统一处......
  • 算法-10--python shuffle函数_python中shuffle()方法的功能详解
     pythonshuffle函数_python中shuffle()方法的功能详解: python的概率分布中,洗牌算法是通过shuffle()方法实现的,shuffle()方法将列表的所有元素打乱,随机排列。Python既可以使用random.shuffle对列表进行洗牌,也可以使用random.shuffle随机播放字符串列表,本文向大家介绍python中......