[SDOI2015][bzoj3994] 约数个数和 [莫比乌斯反演]

题面:

传送门

思路:

首先,我们需要证明一个结论:d(i*j)等于sigma(gcd(x,y)==1),其中x为i的约数,y为j的约数

对于nm的每一个质因子pi分别考虑,设n = pi^ai + n‘,m = pi^bi + m‘

那么显然质因子pi对d(nm)的贡献为(ai+bi+1)

同理,考虑右边的式子,我们发现质数pi对右侧做的贡献仍然是(ai+bi+1),即如下的(x,y)

(pi^ai,1) (pi^(ai-1),1) ..... (1,1) .....(1,pi^(bi-1)) (1,pi^bi)

因此左右两式相同

因此原待求表达式化为如下形式:

由莫比乌斯函数第二情况得:上式可化为

其中g(i)表示前半个式子中的那段东西,相当于d(i)的前缀和

于是O(Tsqrt(min(n,m))轻松解决

顺便说一句,求约数个数也有线性的方法

记录c[i]表示i的最小的质因子的次数

每次更新这个,然后同时用c[i]+1更新d[i*pri[j]]即可

Code:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define ll long long
 6 using namespace std;
 7 inline ll read(){
 8     ll re=0,flag=1;char ch=getchar();
 9     while(ch>‘9‘||ch<‘0‘){
10         if(ch==‘-‘) flag=-1;
11         ch=getchar();
12     }
13     while(ch>=‘0‘&&ch<=‘9‘) re=(re<<1)+(re<<3)+ch-‘0‘,ch=getchar();
14     return re*flag;
15 }
16 ll mu[100010],pri[100010],c[100010],d[100010],cnt;bool vis[100010];
17 void init(ll n){
18     mu[1]=d[1]=c[1]=1;ll i,j,k;
19     for(i=2;i<=n;i++){
20         if(!vis[i]){
21             pri[++cnt]=i;mu[i]=-1;c[i]=1;d[i]=2;
22         }
23         for(j=1;(j<=cnt)&&(i*pri[j]<=n);j++){
24             k=i*pri[j];vis[k]=1;
25             if(i%pri[j]==0){
26                 d[k]=d[i]/(c[i]+1)*(c[i]+2);
27                 c[k]=c[i]+1;break;
28             }
29             mu[k]=-mu[i];
30             d[k]=d[i]*d[pri[j]];c[k]=1;
31         }
32     }
33     for(i=1;i<=n;i++) mu[i]+=mu[i-1];
34     for(i=1;i<=n;i++) d[i]+=d[i-1];
35 }
36 ll n,m;
37 int main(){
38     ll i,j,T=read(),ans;init(50000);
39     while(T--){
40         n=read();m=read();ans=0;
41         if(n>m) swap(m,n);
42         for(i=1;i<=n;i=j+1){
43             j=min(n/(n/i),m/(m/i));
44             ans+=(mu[j]-mu[i-1])*d[n/i]*d[m/i];
45         }
46         printf("%lld\n",ans);
47     }
48 }

原文地址:https://www.cnblogs.com/dedicatus545/p/8492348.html

时间: 2024-10-27 03:12:16

[SDOI2015][bzoj3994] 约数个数和 [莫比乌斯反演]的相关文章

【bzoj3994】[SDOI2015]约数个数和 莫比乌斯反演

题目描述 设d(x)为x的约数个数,给定N.M,求   输入 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组数. 接下来的T行,每行两个整数N.M. 输出 T行,每行一个整数,表示你所求的答案. 样例输入 2 7 4 5 6 样例输出 110 121 题解 莫比乌斯反演 根据 bzoj4176 推出的结论, 那么就有: 预处理mu及其前缀和. 由于要处理多组询问,所以需要用O(n√n)的时间预处理出f,然后对于每组询问分块来求. #include <cstdio> #incl

[SDOI2015] 约数个数和 (莫比乌斯反演)

[SDOI2015]约数个数和 题目描述 设d(x)为x的约数个数,给定N.M,求 \(\sum^N_{i=1}\sum^M_{j=1}d(ij)\) 输入输出格式 输入格式: 输入文件包含多组测试数据.第一行,一个整数T,表示测试数据的组数.接下来的T行,每行两个整数N.M. 输出格式: T行,每行一个整数,表示你所求的答案. 输入输出样例 输入样例#1: 2 7 4 5 6 输出样例#1: 110 121 说明 \(1<=N, M<=50000\) \(1<=T<=50000\

luogu P3327 [SDOI2015]约数个数和 莫比乌斯反演

题面 我的做法基于以下两个公式: \[[n=1]=\sum_{d|n}\mu(d)\] \[\sigma_0(i*j)=\sum_{x|i}\sum_{y|j}[gcd(x,y)=1]\] 其中\(\sigma_0(n)\)表示\(n\)的约数个数 第一个公式是莫比乌斯函数的基本性质,至于第二个公式的证明,可以考虑\(i*j\)中每一个质因子对 \(\sigma_0(i*j)\) 的贡献,对于一个质因子 \(p\) ,若它在 \(i\) 中的次数为 \(k_1\) ,它在 \(j\) 中的次数为

BZOJ 3994 Sdoi2015 约数个数和 莫比乌斯反演

题目大意:求∑ni=1∑mj=1d(ij) 首先我们有一个很神的结论: ∑ni=1∑mj=1d(ij)=∑ni=1∑mj=1?ni??mj?[gcd(i,j)==1] 这个结论是怎么来的呢?我们可以先证明这个: d(nm)=∑i|n∑j|m1?1[gcd(i,j)==1] 显然这个式子的前缀和就是上面的式子 现在我们来证明这个式子是对的 我们分开讨论每一个质数p对答案的贡献 不妨设n=n′?pk1,m=m′?pk2 那么左式中p的贡献显然是k1+k2+1 右式中只考虑p的话,满足要求的数对(i,

[BZOJ 3994]约数个数和 莫比乌斯反演

自己是在是弱,看了半天才看懂题解 写公式实在是麻烦,搬家一份: #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #define N 101000 #define pos(i,a,b) for(int i=(a);i<=(b);i++) using namespace std; #define LL long long int t,n,m; int notpr

Sdoi2015约数个数和题解莫比乌斯反演

题目描述 T组数据,求ΣNi=1ΣMj=1d(ij),d(x)代表x的约数个数. 1≤N,M,T≤105 题解 首先,膜拜一下PoPoQQQ大神及其题解 然后,有一个神奇的结论:ΣNi=1ΣMj=1d(ij)=ΣNi=1ΣMj=1[Ni][Mj][gcd(i,j)=1] 要证上式,只需证d(nm)=Σi|nΣj|m[gcd(i,j)=1],因为上式即为该式的前缀和形式. 分开考虑每个质数p对答案的贡献.设n=n′pk1,m=m′pk2,那p对d(nm)的贡献就是k1+k2+1,对等式右边的贡献是

BZOJ 3994 [SDOI2015]约数个数和 (神定理+莫比乌斯反演)

3994: [SDOI2015]约数个数和 Time Limit: 20 Sec  Memory Limit:128 MB Submit: 239  Solved: 176 [Submit][Status][Discuss] Description 设d(x)为x的约数个数,给定N.M,求   Input 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组数. 接下来的T行,每行两个整数N.M. Output T行,每行一个整数,表示你所求的答案. Sample Input 2 7

洛谷P3327 [SDOI2015]约数个数和 【莫比乌斯反演】

题目 设d(x)为x的约数个数,给定N.M,求\(\sum_{i = 1}^{N} \sum_{j = 1}^{M} d(ij)\) 输入格式 输入文件包含多组测试数据.第一行,一个整数T,表示测试数据的组数.接下来的T行,每行两个整数N.M. 输出格式 T行,每行一个整数,表示你所求的答案. 输入样例 2 7 4 5 6 输出样例 110 121 提示 1<=N, M<=50000 1<=T<=50000 题解 好神的题[是我太弱吧] 首先上来就伤结论.. 题目所求 \(ans

【BZOJ 3994】3994: [SDOI2015]约数个数和(莫比乌斯反演)

3994: [SDOI2015]约数个数和 Description 设d(x)为x的约数个数,给定N.M,求   Input 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组数. 接下来的T行,每行两个整数N.M. Output T行,每行一个整数,表示你所求的答案. Sample Input 2 7 4 5 6 Sample Output 110 121 HINT 1<=N, M<=50000 1<=T<=50000 Source Round 1 感谢yts199