博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ 3994: [SDOI2015]约数个数和 [莫比乌斯反演 转化]
阅读量:5303 次
发布时间:2019-06-14

本文共 2436 字,大约阅读时间需要 8 分钟。

2015

题意:\(d(i)\)为i的约数个数,求\(\sum\limits_{i=1}^n \sum\limits_{j=1}^m d(ij)\)


\(ij\)都爆int了....

一开始想容斥一下用\(d(i)\)\(d(j)\)\(d(ij)\),发现不行...
然后翻题解看到了一步好神的转化:
\[ d(nm) = \sum_{i\mid n} \sum_{j\mid m} [gcd(i,j)=1] \]
晚上再补吧还是没拿草稿纸...
补:
\(Proof.\)

  • 首先注意约数个数 相同的算一个
    约数个数公式\(\prod (a_i+1)\)
    考虑一个质因子,\(p^x,p^y \rightarrow p^x p^y\)
    \(x+y+1\)对应了\(gcd(p^x, 1)...gcd(1, 1)...gcd(1,p^y)\)
    质因子相互独立,乘起来

然后愉♂悦的套路推♂倒

\[ \begin{align*} \sum_{i=1}^n \sum_{j=1}^m d(ij) &= \sum_{i=1}^n \sum_{j=1}^m \sum_{x\mid i} \sum_{y\mid j} [gcd(x,y)=1]\\ 先枚举约数,交换i,j\ x,y\\ &=\sum_{i=1}^n \sum_{j=1}^m \sum_{d\mid i,d\mid j}\mu(d) \frac{n}{i} \frac{m}{i}\\ &=\sum_{d=1}^n \mu(d)\sum_{i=1}^\frac{n}{i} \sum_{j=1}^\frac{m}{i} \frac{n}{id}\frac{m}{jd}\\ &=\sum_{d=1}^n \mu(d) f(\frac{n}{id})f(\frac{m}{jd})\\ \end{align*} \]
问题就是\(f(n)=\sum_{i=1}^n\frac{n}{i}\)怎么求了
可以n根n预处理...
更巧妙的做法是,发现\(f\)就是\(d\)的前缀和,因为\(\frac{n}{i}\)表示的就是\(1..n\)有几个i的倍数

#include 
#include
#include
#include
using namespace std;const int N=5e4+5;typedef long long ll;#define pii pair
#define MP make_pair#define fir first#define sec secondinline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f;} int n, m;int notp[N], p[N], mu[N]; ll f[N]; pii lp[N];void sieve(int n) { mu[1] = 1; f[1] = 1; for(int i=2; i<=n; i++) { if(!notp[i]) p[++p[0]] = i, mu[i] = -1, f[i] = 2, lp[i] = MP(i, 1); for(int j=1; j<=p[0] && i*p[j]<=n; j++) { int t = i*p[j]; notp[t] = 1; if(i%p[j] == 0) { mu[t] = 0; lp[t] = MP(p[j], lp[i].sec + 1); f[t] = f[i] / (lp[i].sec + 1) * (lp[t].sec + 1); break; } mu[t] = -mu[i]; lp[t] = MP(p[j], 1); f[t] = f[i] * (lp[t].sec + 1); } } for(int i=1; i<=n; i++) mu[i] += mu[i-1], f[i] += f[i-1];}ll cal(int n, int m) { ll ans=0; int r; for(int i=1; i<=n; i=r+1) { r = min(n/(n/i), m/(m/i)); ans += (mu[r] - mu[i-1]) * f[n/i] * f[m/i]; } return ans;}int main() { //freopen("in","r",stdin); sieve(N-1); int T=read(); while(T--){ n=read(); m=read(); if(n>m) swap(n, m); printf("%lld\n",cal(n, m)); }}

转载于:https://www.cnblogs.com/candy99/p/6611672.html

你可能感兴趣的文章
MYSQL SHOW VARIABLES简介
查看>>
Selenium2+python自动化-操作浏览器基本方法
查看>>
Nutch2.x常遇问题集锦
查看>>
从AngularJS2谈到前台开发工程化
查看>>
Python的基本类型介绍和可变不可变
查看>>
笔记整理之 Bulk Insert
查看>>
利用ant的javac任务来编译java程序
查看>>
ant—学习记录一
查看>>
根据访问设备自动识别展示手机站或PC站的方法
查看>>
Passwords Gym - 101174E (AC自动机上DP)
查看>>
手工搭建ABP框架(1) - Web项目
查看>>
设置虚拟wifi,手机和电脑可以连接
查看>>
Android下新浪微博和腾讯QQ第三方登陆链接备注
查看>>
线段树专题
查看>>
查看数据库里阻塞和死锁情况
查看>>
函数进阶三(生成器、生成器表达式、匿名函数)
查看>>
Linux ALSA声卡驱动之四:Control设备的创建
查看>>
hashmap两种遍历方法
查看>>
扩展欧几里得
查看>>
实例化Bean
查看>>